我正在尝试将模板化项目(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)给了我一个奇怪的例外:
值不能为空。 参数名称:dp
在System.Windows.DependencyObject.GetValue(DependencyProperty dp) 在System.Windows.Media.Animation.Storyboard.ProcessComplexPath(HybridDictionary clockMappings,DependencyObject targetObject,PropertyPath path,AnimationClock animationClock,HandoffBehavior handoffBehavior,Int64 layer) 在System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock,DependencyObject containsObject,INameScope nameScope,DependencyObject parentObject,String parentObjectName,PropertyPath parentPropertyPath,HandoffBehavior handoffBehavior,HybridDictionary clockMappings,Int64 layer) 在System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock,DependencyObject containsObject,INameScope nameScope,DependencyObject parentObject,String parentObjectName,PropertyPath parentPropertyPath,HandoffBehavior handoffBehavior,HybridDictionary clockMappings,Int64 layer) 在System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containsObject,INameScope nameScope,HandoffBehavior handoffBehavior,Boolean isControllable,Int64 layer) 在System.Windows.Media.Animation.BeginStoryboard.Begin(DependencyObject targetObject,INameScope nameScope,Int64 layer)
等
我通过代码隐藏双重检查ToggleButton的TemplatedParent确实是ContentPresenter,我可以用这样的东西设置ZIndex:
Panel.SetZIndex((sender as ToggleButton).TemplatedParent as UIElement, 99);
但是我想用故事板制作动画,最好使用直接XAML,因为它需要在故事板的持续时间内保持前进,然后再回到原来的位置。
我已经考虑从ItemsControl继承以防止创建ContentPresenter,但这对于看起来应该很容易的事情来说是一个严厉的解决方案。
答案 0 :(得分:0)
以下是这个问题的答案: http://social.msdn.microsoft.com/Forums/en/wpf/thread/7b9b8209-063d-46b2-a03f-98b393cf9514 (作者Min Zhu [MSFT])
您的原始代码不起作用,因为TemplatedParent不是依赖项属性。所以它不是动画的有效路径。
TI82建议的代码是正确的。它仍然不起作用,因为TemplatedParent是Button。但是您要设置动画的元素是项容器。
要为项容器设置动画,可以使用ItemsControl的ItemContainerStyle。 Button.Click是一个冒泡的路由事件,因此它也会从按钮冒泡到项目容器。
请尝试以下代码。
<Window.Resources>
<Storyboard x:Key="MyStoryboard">
<ColorAnimation Storyboard.TargetName="ButtonRect"
Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
To="Red"
Duration="0:0:0.350"
FillBehavior="Stop"/>
</Storyboard>
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="Panel.ZIndex" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContentPresenter}, Mode=OneWayToSource, Path=(Panel.ZIndex)}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Height="60" Margin="0,0,0,-10" >
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="15">
<Rectangle x:Name="ButtonRect" RadiusX="15" RadiusY="15" Fill="AliceBlue" />
</Border>
<TextBlock Text="{Binding}" FontSize="15" TextAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource MyStoryboard}" />
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="MyButtonTemplate">
<Grid>
<Button Style="{StaticResource MyButtonStyle}" />
</Grid>
</DataTemplate>
<Storyboard x:Key="MyStoryboard2">
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)"
BeginTime="0:0:0.000" Duration="0:0:0.350" FillBehavior="Stop">
<Int32KeyFrameCollection>
<DiscreteInt32KeyFrame KeyTime="0:0:0.000" Value="99" />
</Int32KeyFrameCollection>
</Int32AnimationUsingKeyFrames>
</Storyboard>
<Style x:Key="MyItemContainerStyle">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource MyStoryboard2}"/>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="ABCDEF"
ItemTemplate="{StaticResource MyButtonTemplate}"
ItemContainerStyle="{StaticResource MyItemContainerStyle}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>