我有一个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();
}
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
对象,则动画可以正常工作。 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)
进行调用也无效。
答案 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
不起作用,但无论如何上述方法都有效。