11

I have a Popup that contains a "close" button. The popup is opened by a toggle button (its IsOpen property is bound to a ToggleButton as provided by this answer). How can I close the popup when the button is pressed? This is my XAML:

<Canvas x:Name="LayoutRoot">
    <ToggleButton x:Name="ToggleButton"
            Style="{DynamicResource ToggleButtonStyle}" Height="51" Canvas.Left="2.999" Width="50.333" IsHitTestVisible="{Binding ElementName=Popup, Path=IsOpen, Mode=OneWay, Converter={StaticResource BoolInverter}}"/>
    <Popup x:Name="Popup" IsOpen="{Binding IsChecked, ElementName=ToggleButton}" StaysOpen="False" AllowsTransparency="True">
        <Canvas Height="550" Width="550">
            <Grid Height="500" Width="500" Canvas.Left="25" Canvas.Top="25" d:LayoutOverrides="Width, Height, Margin">
                <Grid.Effect>
                    <DropShadowEffect BlurRadius="15" ShadowDepth="0"/>
                </Grid.Effect>
                <Grid.RowDefinitions>
                    <RowDefinition Height="0.132*"/>
                    <RowDefinition Height="0.868*"/>
                </Grid.RowDefinitions>
                <Rectangle x:Name="Background" Fill="#FFF4F4F5" Margin="0" Stroke="Black" RadiusX="6" RadiusY="6" Grid.RowSpan="2"/>
                <Border x:Name="TitleBar" BorderThickness="1" Height="70" VerticalAlignment="Top" Margin="0,0.5,0,0" CornerRadius="5">
                    <DockPanel>
                        <TextBlock TextWrapping="Wrap" Text="FOOBAR POPUP TITLE" FontSize="24" FontFamily="Arial Narrow" Margin="17,0,0,0" d:LayoutOverrides="Height" VerticalAlignment="Center" FontWeight="Bold"/>
                        <Button x:Name="CloseButton" Content="Button" VerticalAlignment="Center" DockPanel.Dock="Right" HorizontalAlignment="Right" Margin="0,0,13,0" Style="{DynamicResource CloseButtonStyle}"/>
                    </DockPanel>
                </Border>
                <Border BorderThickness="1" Height="413" Grid.Row="1" Background="#FF2F2F2F" Margin="12">
                    <Rectangle Fill="#FFF4F4F5" RadiusY="6" RadiusX="6" Stroke="Black" Margin="12"/>
                </Border>
            </Grid>
        </Canvas>
    </Popup>
</Canvas>
Community
  • 1
  • 1
tony19
  • 125,647
  • 18
  • 229
  • 307

3 Answers3

19

A better approach than code behind is to use an event trigger on the button click event:

<Button>
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard>
                    <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsChecked" Storyboard.TargetName="ToggleButton">
                        <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

Disclaimer: I haven't run this code through VS so it might have a typo or 2

Steve Greatrex
  • 15,789
  • 5
  • 59
  • 73
  • @tony19 I had the button in a UserControl so adding Storyboard.Target="{Binding ElementName=DropdownButton}" to BooleanAnimationUsingKeyFrames did the trick for me! – Christian Jul 07 '23 at 10:30
  • @Christian Good to know. WPF was a past life for me :) – tony19 Jul 07 '23 at 20:05
2

Other answers didn't work for me, because I was using a DataTemplate for the buttons inside the popup. After lot's of searching I found that I should use Storyboard.Target instead of Storyboard.TargetName. Otherwise the x:Name was not found and there was some namespace exception.

<ToggleButton x:Name="MyToggleButtonName" Content="{Binding MyToggleButtonString}"/>

And later inside the Popup that has a ListBox which is populated from some ItemsSource:

<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name, Mode=OneWay}"
                  Command="{StaticResource MyCommandThatTakesAParameter}"
                  CommandParameter="{Binding Name}">
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard>
                    <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsChecked" Storyboard.Target="{Binding ElementName=MyToggleButtonName}">
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>

This way it is possible to get a somewhat working ComboBox which can execute commands with the buttons inside it. (A normal ComboBox can't launch commands for some odd reason.)

Jonas Kivi
  • 51
  • 3
1

One way of doing it is to add event handler for your CloseButton:

<Button x:Name="CloseButton" Click="OnButtonClick" Content="Button" VerticalAlignment="Center" DockPanel.Dock="Right" HorizontalAlignment="Right" Margin="0,0,13,0" Style="{DynamicResource CloseButtonStyle}"/>

And in OnButtonClick event handler set state of your

TuggleButton.IsChecked = false;

I have't tested code in VS, so there might be some typos

Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179