Souvik Basu
Souvik Basu

Reputation: 3139

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" />                      
                            </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?

Upvotes: 7

Views: 14520

Answers (5)

Smagin Alexey
Smagin Alexey

Reputation: 345

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)

Upvotes: 0

Souvik Basu
Souvik Basu

Reputation: 3139

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.

Upvotes: 8

Prince Ashitaka
Prince Ashitaka

Reputation: 8773

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

Upvotes: 0

ajay_whiz
ajay_whiz

Reputation: 17931

try changing your event trigger to

<EventTrigger RoutedEvent="Popup.Opened">

Upvotes: -1

mdm20
mdm20

Reputation: 4563

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.

Upvotes: 1

Related Questions