Search code examples
c#wpfanimationstoryboardeventtrigger

EventTrigger listening to Loaded is triggered twice?


Firstly, I am not really sure if it is actually triggered twice. The Loaded event if tested in code behind is triggered just once (even tried using AddHandler accepting the third argument handledEventsToo). However it looks very likely that. I have a Storyboard setup in XAML and should be run just once when Loaded is raised. But it seems to start 2 times, especially the second time is right after the window is shown.

I know that because I have an attached property used on a DoubleAnimation inside the Storyboard. This attached property has 1 propertyChangedCallback handler. This handler however is triggered twice with the same value of e.NewValue (from the argument). It should not be triggered twice like that. I can determine the target (which is animated) and set some attached flag to mark something has been done on it to prevent the problem of twice triggering, but that will also prevent other actual triggers (which are not from the Loaded). The DoubleAnimation itself is however created newly for each trigger (so I also cannot mark any flag on it because each time propertyChangedCallback is triggered is another time of another DoubleAnimation, no way to flag and prevent execution).

Here is the code, just simple to test:

public class TestOwner {
    public static readonly DependencyProperty TestProperty =
        DependencyProperty.RegisterAttached("Test", typeof(bool), typeof(TestOwner), new PropertyMetadata(testChanged));
    public static bool GetTest(DependencyObject o)
    {
        return (bool) o.GetValue(TestProperty);
    }
    public static void SetTest(DependencyObject o, bool value)
    {
        o.SetValue(TestProperty, value);
    }
    static private void testChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    { //Mark some break point here and run it, you'll see it's stopped 
      //here twice, the second time is right after the window is shown.
      //...
    }
}

XAML:

<FrameworkElement>
        <FrameworkElement.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation From="20000" To="0" 
                                        Duration="00:00:20" 
                                        Storyboard.TargetName="someName"
                                         local:TestOwner.Test="True"/>

                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </FrameworkElement.Triggers>
</FrameworkElement>

I would like to avoid this twice triggering as well as understand why it is so.


Solution

  • Well, in fact the EventTrigger is triggered just once. Almost what I said in my question are wrong perception. I've found out that looks like Storyboard clones the DoubleAnimation and this actually clones even attached properties causing 2 times of entering the propertyChanged callback handler. The first time is for the original DoubleAnimation. The second time is for the cloned DoubleAnimation, it may be actually cloned and run when the Loaded is raised, so it occurs right after the window is shown as I said before.

    At least now I understand the problem and also more debugging showed me that that kind of 2 times entering the handler won't affect any serious problem. So this problem seems to be solved to me.