【问题标题】:Programmatically creating a Storyboard in a WPF ControlTemplate以编程方式在 WPF ControlTemplate 中创建情节提要
【发布时间】:2014-06-27 21:08:46
【问题描述】:

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

我在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();
}

Template 是一个 ControlTemplate,包含以下 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 对象包装,则动画将起作用。例如

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) 调用也没有任何作用。

【问题讨论】:

  • 您可能会创建一个依赖属性并将您的转换绑定到它并为该属性设置动画以便于操作。访问控件或数据模板中的对象是一项棘手的工作。您也可以在运行应用程序时尝试在输出窗口中查找任何数据错误。
  • 出于某种原因,我认为如果您使用可视状态管理器,这会更容易,一个示例虽然不是您正在寻找的,但 silverlightshow.net/items/…
  • 幻灯片转换并非易事。你最好使用像Transitionals这样的预先存在的库。

标签: c# wpf xaml animation


【解决方案1】:

最终,多种因素的结合使其发挥了作用。首先,使用Storyboard.SetTargetName 而不是Storyboard.SetTarget。其次将模板上下文传递给Begin() 方法。例如

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

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

【讨论】:

    猜你喜欢
    • 2011-02-01
    • 2017-10-19
    • 2016-10-08
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多