如何在 WPF 中对模板化父级 Panel.ZIndex 进行动画处理?
我正在尝试在数据绑定堆栈面板中向前推进模板化项目(ZIndex)。由于 stackpanel 为其中的每个项目创建一个 ContentPresenter,因此我的视觉树如下所示:
ItemsControl
Border
ItemsPresenter
StackPanel
ContentPresenter
ToggleButton
ContentPresenter
ToggleButton
ContentPresenter
ToggleButton
单击 ToggleButton 时,它会触发如下所示的故事板:
<Storyboard x:Key="MyStoryboard" >
<Int32AnimationUsingKeyFrames BeginTime="0:0:0.000" Duration="0:0:0.350"
Storyboard.TargetProperty="TemplatedParent.(Panel.ZIndex)" >
<Int32KeyFrameCollection>
<DiscreteInt32KeyFrame KeyTime="0:0:0.000" Value="99" />
</Int32KeyFrameCollection>
</Int32AnimationUsingKeyFrames>
</Storyboard>
<Style x:Key="SubStateOptionButtonStyle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<!-- Toggle Button Contents here -->
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource MyStoryboard}" />
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
然而,TemplatedParent.(Panel.ZIndex) 给了我一个奇怪的异常:
Value不能为空。 参数名称:
System.Windows.DependencyObject.GetValue 处的 dp(DependencyProperty dp) 在System.Windows.Media.Animation.Storyboard.ProcessComplexPath(HybridDictionaryclockMappings,DependencyObject targetObject,PropertyPath路径,AnimationClock动画时钟,HandoffBehavior handoffBehavior,Int64层) 在System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(时钟currentClock,DependencyObject containsObject,INameScope nameScope,DependencyObjectparentObject,StringparentObjectName,PropertyPathparentPropertyPath,HandoffBehavior handoffBehavior,HybridDictionaryclockMappings,Int64层) 在System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(时钟currentClock,DependencyObject containsObject,INameScope nameScope,DependencyObjectparentObject,StringparentObjectName,PropertyPathparentPropertyPath,HandoffBehavior handoffBehavior,HybridDictionaryclockMappings,Int64层) 在System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containsObject,INameScope nameScope,HandoffBehavior handoffBehavior,Boolean isControllable,Int64层) 在 System.Windows.Media.Animation.BeginStoryboard.Begin(DependencyObject targetObject, INameScope nameScope, Int64 layer)
等。
我已经通过代码隐藏仔细检查了 ToggleButton 的 TemplatedParent 确实是 ContentPresenter,我可以使用类似的内容设置 ZIndex this:
Panel.SetZIndex((sender as ToggleButton).TemplatedParent as UIElement, 99);
但我想使用故事板为其制作动画,最好使用直接的 XAML,因为它需要在故事板的持续时间内保持前进,然后回到原来的地方。
我考虑过从 ItemsControl 继承以防止创建 ContentPresenter,但对于看起来应该很容易的事情来说,这是一个严厉的解决方案。
I'm attempting to bring a templated item forward (ZIndex) in a databound stackpanel. Since a stackpanel creates a ContentPresenter for each item within it, my visual tree looks like this:
ItemsControl
Border
ItemsPresenter
StackPanel
ContentPresenter
ToggleButton
ContentPresenter
ToggleButton
ContentPresenter
ToggleButton
When a ToggleButton is clicked, it fires off a storyboard like this:
<Storyboard x:Key="MyStoryboard" >
<Int32AnimationUsingKeyFrames BeginTime="0:0:0.000" Duration="0:0:0.350"
Storyboard.TargetProperty="TemplatedParent.(Panel.ZIndex)" >
<Int32KeyFrameCollection>
<DiscreteInt32KeyFrame KeyTime="0:0:0.000" Value="99" />
</Int32KeyFrameCollection>
</Int32AnimationUsingKeyFrames>
</Storyboard>
<Style x:Key="SubStateOptionButtonStyle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<!-- Toggle Button Contents here -->
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource MyStoryboard}" />
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, the TemplatedParent.(Panel.ZIndex) gives me a strange exception:
Value cannot be null.
Parameter name: dp
at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
at System.Windows.Media.Animation.Storyboard.ProcessComplexPath(HybridDictionary clockMappings, DependencyObject targetObject, PropertyPath path, AnimationClock animationClock, HandoffBehavior handoffBehavior, Int64 layer)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
at System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containingObject, INameScope nameScope, HandoffBehavior handoffBehavior, Boolean isControllable, Int64 layer)
at System.Windows.Media.Animation.BeginStoryboard.Begin(DependencyObject targetObject, INameScope nameScope, Int64 layer)
etc.
I've double checked via code-behind that the ToggleButton's TemplatedParent is indeed the ContentPresenter and I can set the ZIndex with something like this:
Panel.SetZIndex((sender as ToggleButton).TemplatedParent as UIElement, 99);
But I'd like to animate it with a storyboard, preferably with straight XAML, since it needs to stay forward for the duration of the storyboard, then go back to where it was.
I've considered inheriting from ItemsControl to prevent the ContentPresenter from being created but that's a heavy-handed solution to something that seems like it should be easy.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是这个问题的答案:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/7b9b8209-063d-46b2-a03f-98b393cf9514
(作者:Min Zhu [MSFT])
您的原始代码不起作用,因为 TemplatedParent 不是依赖项属性。所以它不是动画的有效路径。
TI82 建议的代码是正确的。它仍然不起作用,因为 TemplatedParent 是按钮。但您想要设置动画的元素是项目容器。
要为项目容器设置动画,您可以使用 ItemsControl 的 ItemContainerStyle。 Button.Click 是一个冒泡路由事件,因此它也会从按钮冒泡到项目容器。
尝试以下代码。
Here is the answer to this question:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/7b9b8209-063d-46b2-a03f-98b393cf9514
(by Min Zhu [MSFT])
Your original code doesn't work because TemplatedParent is not a dependency property. So it is not a valid path for animation.
The code TI82 suggests is correct. It still doesn't work because the TemplatedParent is the Button. But the element you want to animate is the item container.
To animate the item container, you can use ItemsControl's ItemContainerStyle. Button.Click is a bubbling routed event, so it will bubble from the button to the item container as well.
Try the following code.