WPF Popup event handling - How to get triggered when Popup opens
I created a WPF Popup which contains a grid with border. There is some animation associated with the border which I want to be triggered every time the Popup opens.
Currently the code is like this
<Popup x:Name="myPopUp" >
<Border x:Name="myBorder" >
<Border.Triggers>
<EventTrigger RoutedEvent="Popup.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="myBorder"
Storyboard.TargetProperty="Height"
From="10" To="255" Duration="0:0:0.20" />
开发者_StackOverflow </Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid />
</Border>
</Popup>
As per the code the border shows up the animation for the first time the popup opens. What change do I need to make to trigger the border animation every time the Popup opens?
As per suggestions given here and a little bit expireince now (I asked this a year back :) ), I could figure out the solution.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<Style x:Key="popupStyle" TargetType="{x:Type Popup}" >
<Style.Triggers>
<Trigger Property="IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Height"
From="10" To="255" Duration="0:0:0.20" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Width="100" Height="100" Click="Button_Click"></Button>
<Popup Name="popUp" Width="100" Height="100" Style="{StaticResource popupStyle}" >
<Border x:Name="myBorder" Background="Blue"/>
</Popup>
</Grid>
and a sample code behind to trigger the popup..
private void Button_Click(object sender, RoutedEventArgs e)
{
popUp.PlacementTarget = (Button)sender;
popUp.IsOpen = true;
}
Although I can only animate the Popup and not the Border here, it pretty much gives the same result.
I'm not sure if the popup gets focus when it opens, but you could use the GotFocus event if it does. Alternatively, you could try using a datatrigger on the is IsOpen property. I think you'd have to put that in a style though instead of inline.
You can achieve this by listening to the IsOpen
dependency property like
public MainWindow()
{
InitializeComponent();
//// Listening to the IsOpen dependency property of the Popup.
this.SetBinding(PopupIsOpenProperty, new Binding() { Source = this.popupContainer, Path = new PropertyPath("IsOpen") });
}
/// <summary>
/// Gets or sets a value indicating whether [popup is open].
/// </summary>
/// <value><c>true</c> if [popup is open]; otherwise, <c>false</c>.</value>
public bool PopupIsOpen
{
get { return (bool)GetValue(PopupIsOpenProperty); }
set { SetValue(PopupIsOpenProperty, value); }
}
// Using a DependencyProperty as the backing store for PopupIsOpen. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PopupIsOpenProperty =
DependencyProperty.Register("PopupIsOpen", typeof(bool), typeof(MainWindow), new PropertyMetadata(false,
(dependencyObject, e) =>
{
var mainWindow = (MainWindow)dependencyObject;
if (mainWindow != null &&
(bool)e.NewValue == true)
{
//// Raise your event here... like
//// mainWindow.RaisePopupOpened();
System.Diagnostics.Debug.WriteLine("Popup Open Triggered");
}
}));
private void button_MouseLeave(object sender, MouseEventArgs e)
{
this.popupContainer.IsOpen = false;
}
private void button_MouseMove(object sender, MouseEventArgs e)
{
//// Setting the popup position
var p = e.GetPosition(sender as UIElement);
this.popupContainer.HorizontalOffset = p.X;
this.popupContainer.VerticalOffset = p.Y;
//// Enabling popup when it is hover on the button
this.popupContainer.IsOpen = true;
}
<!-- XAML Starts here-->
<Grid>
<Button x:Name="button1" Content="This is a sample text" MouseMove="button_MouseMove" MouseLeave="button_MouseLeave" Width="100" Height="25" />
<Popup x:Name="popupContainer" IsHitTestVisible="False" >
<Grid Background="White">
<TextBlock Text="{Binding Content, ElementName=button}" />
</Grid>
</Popup>
</Grid>
HTH
In App.xaml.cs or in another starting class instance you need add:
var field = typeof(PresentationSource).GetField("RootSourceProperty", BindingFlags.NonPublic | BindingFlags.Static);
var property = (DependencyProperty)field.GetValue(null);
property.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(property.DefaultMetadata.DefaultValue, OnHwndSourceChanged));
Where, RootSourceProperty
is private field DependecyProperty
of PresentationSource
. Its property use when HwndSource is created and set RootVisual. So you need just use property changed call back of RootSourceProperty
:
private static void OnHwndSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
This is nice because, you can use it in your all Application and for all HwndSource (Popup
, Window
or Custom controls, where you are using HwndSource
)
try changing your event trigger to
<EventTrigger RoutedEvent="Popup.Opened">
精彩评论