如何通过从另一个数据模板触发动画来为在另一个数据模板中定义的元素设置动画

时间:2014-07-16 16:21:37

标签: c# wpf mvvm storyboard custom-controls

所以我正在制作自定义控件,在我的控制模板中,我有两个ItemsControl。我想为数据模板内的用户控件(更改不透明度)设置动画,以便从另一个Stackpanel数据模板中定义的ItemsControl触发的鼠标进入/离开事件。但是,由于Storyboard需要TargetName,我无法使用这种方式访问​​用户控件。我能做些什么来实现这个目标?

示例代码:

<Style TargetType="{x:Type pie:PieChartControl}">

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type pie:PieChartControl}">

                <Grid>

                    <ItemsControl
                        ItemsSource="{Binding slices, RelativeSource={RelativeSource TemplatedParent}}"
                        >
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate >
                                <Grid ... />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>

                                <pie:Slice
                                    Opacity="{Binding opacity}"
                                    x:Name="TheSlice">
                                </pie:Slice>

                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>

                    <Grid
                        DataContext="{TemplateBinding DataContext}"
                        >
                        <ItemsControl
                            ItemsSource="{Binding slices, RelativeSource={RelativeSource TemplatedParent}}">

                            <ItemsControl.ItemTemplate>
                                <DataTemplate>

                                    <Grid>
                                        <StackPanel>
                                            <StackPanel.Triggers>
                                                <EventTrigger RoutedEvent="MouseEnter">
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <DoubleAnimation Storyboard.TargetName="TheSlice"
                                                                    Storyboard.TargetProperty="Opacity" 
                                                                    To="0.5"/>
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger>
                                                <EventTrigger RoutedEvent="MouseLeave">
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <DoubleAnimation Storyboard.TargetName="TheSlice"
                                                                    Storyboard.TargetProperty="Opacity"
                                                                    To="1"/>
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger>

                                            </StackPanel.Triggers>

                                            <Rectangle ... />

                                            <TextBlock ... />
                                        </StackPanel>
                                    </Grid>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Grid>
                </Grid>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

2 个答案:

答案 0 :(得分:0)

就像抬头一样,我认为ItemsControl不会很容易在这里工作,因为它和它的项目不知道鼠标当前是什么项目,因为它们是不可选择的。

虽然它没有回答你的问题,但我想你会想看看Selector并使用它或其中一个子类,如ListBox。请注意ListBoxItemListBox中的每个项目都是),它有一个IsMouseOver。在这种情况下,您可以更轻松地让ListBoxItem控件模板执行以下操作:

<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver"
                Value="True">
        <Setter Property="Opacity"
                Value="0.5" />
    </Trigger>
</ControlTemplate.Triggers>

答案 1 :(得分:0)

我能解决这个问题的唯一方法就是回到视图模型。触发动画的元素绑定到其DataContext中的属性和该属性的setter,而不是为位于另一个数据模板中的元素提供属性的动画(在本例中为opacity)。该属性当然必须绑定到动画元素的属性。我很幸运能够为这两个元素提供相同的datacontext,但如果不是这样,那么我认为可以通过Freezable或其他方式实现的DataContext Proxy类来实现。