How do I create a BeginStoryboard in code for WPF?

I have the following XAML and I want to convert it to the code behind, I was able to create the animation successfully, so the control disappears as expected, but I am having trouble converting the IsMouseOver trigger to code

 <DataTemplate.Triggers>
            <EventTrigger RoutedEvent="Control.Loaded"
                          SourceName="NotificationGrid">
                <BeginStoryboard x:Name="BeginNotificationStoryboard">
                    <Storyboard x:Name="NotificationStoryboard">
                        <DoubleAnimation Storyboard.TargetName="NotificationGrid"
                                         From="0.01"
                                         To="1"
                                         Storyboard.TargetProperty="Opacity"
                                         Duration="0:0:0.5" />

                        <DoubleAnimation Storyboard.TargetName="NotificationGrid"
                                         From="1"
                                         To="0"
                                         Storyboard.TargetProperty="Opacity"
                                         Duration="0:0:0.5"
                                         BeginTime="0:0:5" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <Trigger Property="IsMouseOver"
                     Value="True">
                <Trigger.EnterActions>
                    <SeekStoryboard Offset="0:0:3"
                                    BeginStoryboardName="BeginNotificationStoryboard" />
                    <PauseStoryboard BeginStoryboardName="BeginNotificationStoryboard" />
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <SeekStoryboard Offset="0:0:3"
                                    BeginStoryboardName="BeginNotificationStoryboard" />
                    <ResumeStoryboard BeginStoryboardName="BeginNotificationStoryboard" />
                </Trigger.ExitActions>
            </Trigger>
        </DataTemplate.Triggers>
    </DataTemplate>

      

The problem I ran into was how to find out what the "BeginStoryboardName" value should mean for instances of the SeekStoryboard classes, since I didn't have to instantiate a BeginStoryboard for the boot animation to work properly.

var loadingAnimation = new DoubleAnimation(0.01, 1, new Duration(TimeSpan.FromSeconds(0.5)));
var closingAnimation = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(3)))
{
    BeginTime = TimeSpan.FromSeconds(5)
};

Storyboard.SetTarget(loadingAnimation, AssociatedObject);
Storyboard.SetTarget(closingAnimation, AssociatedObject);

Storyboard.SetTargetProperty(loadingAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTargetProperty(closingAnimation, new PropertyPath(UIElement.OpacityProperty));

Storyboard.SetTarget(loadingAnimation, AssociatedObject);
Storyboard.SetTarget(closingAnimation, AssociatedObject);

var storyboard = new Storyboard();
storyboard.Children.Add(loadingAnimation);
storyboard.Children.Add(closingAnimation);

var enterSeekStoryboard = new SeekStoryboard
{
    Offset = TimeSpan.FromSeconds(5),
    // What value should go here?
    BeginStoryboardName = ""
};

var exitSeekStoryboard = new SeekStoryboard
{
    Offset = TimeSpan.FromSeconds(5),
    // What value should go here?
    BeginStoryboardName = ""
};

var trigger = new Trigger
{
    Property = UIElement.IsMouseOverProperty,
    Value = true
};

trigger.EnterActions.Add(enterSeekStoryboard);
trigger.ExitActions.Add(exitSeekStoryboard);

var style = new Style();
style.Triggers.Add(trigger);

AssociatedObject.Style = style;

storyboard.Completed += HandleOnCompleted;
storyboard.Begin();

      

+3


source to share


2 answers


Your complete code will be something like this. I left some comments to point out some of the problems I found:



var loadingAnimation = new DoubleAnimation(0.01, 1, new Duration(TimeSpan.FromSeconds(0.5)));
var closingAnimation = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(3)))
{
    BeginTime = TimeSpan.FromSeconds(5)
};

Storyboard.SetTarget(loadingAnimation, AssociatedObject);
Storyboard.SetTarget(closingAnimation, AssociatedObject);

Storyboard.SetTargetProperty(loadingAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTargetProperty(closingAnimation, new PropertyPath(UIElement.OpacityProperty));

Storyboard.SetTarget(loadingAnimation, AssociatedObject);
Storyboard.SetTarget(closingAnimation, AssociatedObject);

var storyboard = new Storyboard();
storyboard.Children.Add(loadingAnimation);
storyboard.Children.Add(closingAnimation);
// Subscription to events must be done at this point, because the Storyboard object becomes frozen later on
storyboard.Completed += HandleOnCompleted;

string storyBoardName = "BeginNotificationStoryboard";

// We define the BeginStoryBoard action for the EventTrigger
var beginStoryboard = new BeginStoryBoard();
beginStoryboard.Name = storyBoardName;
beginStoryboard.Storyboard = storyboard;

// We create the EventTrigger
var eventTrigger = new EventTrigger(Control.LoadedEvent);
eventTrigger.Actions.Add(beginStoryboard);

// Actions for the entering animation
var enterSeekStoryboard = new SeekStoryboard
{
    Offset = TimeSpan.FromSeconds(5),
    BeginStoryboardName = storyBoardName
};
var enterPauseStoryboard = new PauseStoryboard
{
    BeginStoryboardName = storyBoardName
};

// Actions for the exiting animation
var exitSeekStoryboard = new SeekStoryboard
{
    Offset = TimeSpan.FromSeconds(5),
    BeginStoryboardName = storyBoardName
};
var exitResumeStoryboard = new ResumeStoryboard
{
    BeginStoryboardName = storyBoardName
};

var trigger = new Trigger
{
    Property = UIElement.IsMouseOverProperty,
    Value = true
};

trigger.EnterActions.Add(enterSeekStoryboard);
trigger.EnterActions.Add(enterPauseStoryboard);
trigger.ExitActions.Add(exitSeekStoryboard);
trigger.ExitActions.Add(exitResumeStoryboard);

var style = new Style();
// The name of the Storyboard must be registered so the actions can find it
style.RegisterName(storyBoardName, beginStoryboard);
// Add both the EventTrigger and the regular Trigger
style.Triggers.Add(eventTrigger);
style.Triggers.Add(trigger);

AssociatedObject.Style = style;

// No need for storyboard.Begin()

      

+3


source


You have created a Storyboard, but not a BeginStoryboard. So do it like this:

var storyboard = new Storyboard();
storyboard.Children.Add(loadingAnimation);
storyboard.Children.Add(closingAnimation);

var beginStoryboard = new BeginStoryboard(){ Name="BeginNotificationStoryboard", Storyboard = storyboard};

var enterSeekStoryboard = new SeekStoryboard
{
    Offset = TimeSpan.FromSeconds(5),
    // What value should go here?
    BeginStoryboardName = "BeginNotificationStoryboard"
};

      

Don't forget to add your startStoryboard to the EventTrigger as you did before.



In fact, the XAML source used the BeginNotificationStoryboard identifier only to remove duplicate code. If you don't want this anymore, just add it to TriggerActions like this:

trigger.EnterActions.Add(beginStoryboard);

      

Than you do not need to give a name.

+1


source







All Articles