I have a popup named "ContextPopup" defined in a ResourceDictionary as follows:
<ControlTemplate x:Key="UXIconComboBoxControlTemplate" TargetType="{x:Type controls:UXIconComboBox}" >
<ControlTemplate.Resources>
<converters:IconComboBoxDropdownHorizontalOffsetMultiConverter x:Key="ComboBoxDropdownHorizontalOffsetConverter"/>
</ControlTemplate.Resources>
<Grid
x:Name="rootGrid"
Width="{TemplateBinding HitAreaWidth}"
Height="{TemplateBinding HitAreaHeight}"
Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:ExtendedHitAreaButton
Grid.Row="0"
x:Name="OpenPopupIconButton"
IsDefault="True"
Style="{StaticResource UXIconComboBoxButtonStyle}">
<controls:ExtendedHitAreaButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="ContextPopup"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0.25" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</controls:ExtendedHitAreaButton.Triggers>
</controls:ExtendedHitAreaButton>
<Popup
x:Name="ContextPopup"
Grid.Row="1"
Placement="Bottom"
PlacementTarget="{Binding ElementName=OpenPopupIconButton}"
StaysOpen="False"
PreviewKeyDown="ContextPopup_PreviewKeyDown">
<Popup.HorizontalOffset>
<MultiBinding Converter="{StaticResource ComboBoxDropdownHorizontalOffsetConverter}">
<Binding ElementName="OpenPopupIconButton" Path="ActualWidth"/>
<Binding ElementName="PopupListBox" Path="ActualWidth"/>
</MultiBinding>
</Popup.HorizontalOffset>
<ListBox
x:Name="PopupListBox"
ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}}"
ItemTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource TemplatedParent}}"
Loaded="PopupListBox_OnLoaded"
KeyboardNavigation.IsTabStop="True"
KeyboardNavigation.TabNavigation="Continue"
BorderThickness="0"/>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IconComboBoxSemanticColorType}" Value="Default"/>
<Condition Binding="{Binding Path=IsOpen, ElementName=ContextPopup}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="{DynamicResource BrushIconComboBox_Popup_Open_Background}" />
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
The Popup has a PreviewKeyDown method called "ContextPopup_PreviewKeyDown" that is defined in a ResourceDictionary code-behind file as follows:
private void ContextPopup_PreviewKeyDown(object sender, KeyEventArgs e)
{
var popupControl = sender as Popup;
if (e.Key == Key.Escape)
{
popupControl.IsOpen = false;
}
}
When the popup is displayed, I press the ESC button and have verified that the ContextPopup_PreviewKeyDown method is called and the popupControl.IsOpen property is set to false, but the popup does not close.
Can anyone explain why the popup does not close and what to do about it.
Thanks for any help.
You can't modify the property value as long as a Storyboard
is still animating it. Either stop the Storyboard
explicitly or apply another animation to modify the value.
The following example uses the VisualStateManager
to trigger the animations.
<ControlTemplate TargetType="{x:Type local:UXIconComboBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PopupStates">
<VisualState x:Name="PopupClosed">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_ContextPopup"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0.25"
Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PopupOpen">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_ContextPopup"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0.25"
Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Button x:Name="PART_OpenPopupIconButton" />
<Popup x:Name="PART_ContextPopup"
AllowsTransparency="True">
<TextBox Text="Hello World!" />
</Popup>
</Grid>
</Border>
</ControlTemplate>
public class UXIconComboBox : Control
{
private ButtonBase? PART_OpenPopupIconButton { get; set; }
private UIElement? PART_ContextPopup { get; set; }
static UXIconComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(UXIconComboBox), new FrameworkPropertyMetadata(typeof(UXIconComboBox)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_OpenPopupIconButton = GetTemplateChild("PART_OpenPopupIconButton") as ButtonBase;
this.PART_OpenPopupIconButton.Click += OpenPopupIconButton_Click;
this.PART_ContextPopup = GetTemplateChild("PART_ContextPopup") as UIElement;
this.PART_ContextPopup.PreviewKeyDown += ContextPopup_PreviewKeyDown;
}
protected void ContextPopup_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
_ = VisualStateManager.GoToState(this, "PopupClosed", true);
}
}
private void OpenPopupIconButton_Click(object sender, System.Windows.RoutedEventArgs e)
=> _ = VisualStateManager.GoToState(this, "PopupOpen", true);
}