以编程方式在WPF ControlTemplate中创建Storyboard

时间:2014-06-26 14:56:58

标签: c# wpf xaml animation

我有一个WPF应用程序,可以在模板Pages中加载NavigationWindow。我想在加载新页面时实现幻灯片转换,并且由于窗口可以调整大小,因此我需要以编程方式确定转换的目标值。

我在NavigationWindow代码隐藏中尝试了以下操作,但它在触发时无效。根据调试器的确定,PageContentContainerTransform也正确定位。

public void DoTransition()
{
    double targetX = this.ActualWidth;

    this.TransitionStoryboard.Stop();
    this.TransitionStoryboard.Children.Clear();
    IEasingFunction easing = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
    DoubleAnimation translateXAnim = new DoubleAnimation() {
        To = targetX,
        Duration = TimeSpan.FromMilliseconds(250),
        EasingFunction = easing,
    };

    DependencyObject d = this.Template.FindName("pageContentContainerTransform", this) as DependencyObject;
    Storyboard.SetTarget(translateXAnim, d);

    Storyboard.SetTargetProperty(translateXAnim, new PropertyPath(TranslateTransform.XProperty));
    this.TransitionStoryboard.Children.Add(translateXAnim);
    this.TransitionStoryboard.Begin();
}

TemplateControlTemplate,其中包含以下XAML,

...
<ContentPresenter 
    Grid.Row="1"
    x:Name="pageContentContainer"
    MaxHeight="{StaticResource ContentWindowMaxHeight}"
    MaxWidth="{StaticResource ContentWindowMaxWidth}"
    RenderTransformOrigin="0.5,0.5">
    <ContentPresenter.RenderTransform>
        <TranslateTransform x:Name="pageContentContainerTransform" X="0" Y="0" />
    </ContentPresenter.RenderTransform>
</ContentPresenter>
...

为什么没有效果?

更新

如果直接为元素设置动画而不包装Storyboard对象,则动画可以正常工作。 E.g。

public void DoTransition()
{
    double targetX = this.ActualWidth;

    this.TransitionStoryboard.Stop();
    this.TransitionStoryboard.Children.Clear();
    IEasingFunction easing = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
    DoubleAnimation translateXAnim = new DoubleAnimation() {
        To = targetX,
        Duration = TimeSpan.FromMilliseconds(250),
        EasingFunction = easing,
    };

    TranslateTransform t = this.Template.FindName("pageContentContainerTransform", this) as TranslateTransform;
    t.BeginAnimation(TranslateTransform.XProperty, translateXAnim);

}

然而,大概你错过了Storyboard对象提供的动画的一些不错的控制元素,例如管理动画(停止,开始等)。故事板对象上的.Begin()似乎可能存在与在模板中使用相关的参数,但是使用.Begin(this, this.Template)进行调用也无效。

1 个答案:

答案 0 :(得分:1)

最后,一系列因素使其发挥作用。首先,使用Storyboard.SetTargetName而不是Storyboard.SetTarget。其次,将模板上下文传递给Begin()方法。 E.g。

public void DoTransition()
{
    double targetX = this.ActualWidth;

    this.TransitionStoryboard.Stop();
    this.TransitionStoryboard.Children.Clear();
    IEasingFunction easing = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
    DoubleAnimation translateXAnim = new DoubleAnimation() {
        To = targetX,
        Duration = TimeSpan.FromMilliseconds(250),
        EasingFunction = easing,
    };

    // 1. Refer to the element by Name
    Storyboard.SetTargetName(translateXAnim, "pageContentContainerTransform");
    Storyboard.SetTargetProperty(translateXAnim, new PropertyPath(TranslateTransform.XProperty));
    this.TransitionStoryboard.Children.Add(translateXAnim);
    // 2. Pass in the template context here
    this.TransitionStoryboard.Begin(this, this.Template);    
}

当您考虑SetTargetProperty正确识别模板中的元素时,我不清楚为什么FindName不起作用,但无论如何上述方法都有效。