如何在WPF的代码后台中创建BeginStoryboard?

3

我有以下的XAML代码,希望将其转换为后台代码。我已经成功地创建了动画效果,以便控件按预期淡入和淡出,但我在将IsMouseOver触发器转换为后台代码时遇到了问题:

 <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>

我遇到的问题是,我如何知道SeekStoryboard类实例的'BeginStoryboardName'值应该是什么,因为我没有必要创建一个BeginStoryboard实例来使加载时的动画按预期工作。

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();

我猜...你最终还是得创建它们?你碰巧让它工作了,只是因为动画默认情况下会在控件加载时自动启动。但这对于鼠标悬停不起作用。 - almulo
2个回答

3

你的完整代码将类似于这样。我留下了一些注释来指出我发现的一些问题:

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()

1
您已经创建了Storyboard,但是没有创建BeginStoryboard。因此,请按照以下方式进行操作:
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"
};

不要忘记像之前一样将你的beginStoryboard添加到EventTrigger中。 实际上,原始的XAML代码只是使用BeginNotificationStoryboard id来删除一些重复的代码。 如果你不再需要它,只需将其添加到TriggerActions中,就像这样:
trigger.EnterActions.Add(beginStoryboard);

那么您就不需要指定名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接