【问题标题】:WPF DataTemplate: Location of inflated storyboardWPF DataTemplate:膨胀故事板的位置
【发布时间】:2013-07-01 20:20:14
【问题描述】:

我有一个DataTemplate 用于ItemsControl,它工作正常。在DataTemplate 中有一个DataTrigger,其中包含一个BeginStoryboard EnterAction。我正在尝试将情节提要的 Completed 事件连接到代码中的某些内容,特别是数据对象上的方法,但我可以灵活处理——目前我只想让它运行任何一段 C# 代码动画完成后。

Completed XAML 属性指定一个值不会编译,因为该属性是在模板内定义的,因此没有特定的方法可以连接。所以我需要使用后面的代码来手动连接事件。

为此,我使用 Snoop 查看了应用程序,试图找到膨胀模板 Storyboards 在逻辑或可视树中的最终位置。到目前为止,我所看到的只是为每个项目创建的ContentControl,并设置了ContentTemplate。每个ContentControlContent 属性设置为其对应的数据对象。 ContentTemplate 属性包含 Triggers 集合,其中包含 EnterActions 和最终的 Storyboard。我的问题是,是否所有项目都为其ContentTemplate 属性共享一个模板实例,还是每个项目都有自己的副本?如果他们共享一个,那么膨胀的触发器和故事板是在哪里创建的?

我已经提取了我的 XAML 的相关部分:

<Style TargetType="{x:Type m:MyControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type m:MyControl}">
                <Grid Name="ControlRoot" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                    <!-- ... -->
                    <ItemsControl ItemsSource="...">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate DataType="{x:Type m:MyDataType}">
                                <Grid>
                                    <Ellipse Name="IconHighlight1" Fill="{DynamicResource GoldRadialFade}" Width="70" Height="70" StrokeThickness="0" Opacity="0"/>
                                </Grid>
                                <DataTemplate.Triggers>
                                    <DataTrigger Binding="{Binding Highlighted}" Value="True">
                                        <DataTrigger.EnterActions>
                                            <BeginStoryboard HandoffBehavior="Compose">
                                                <Storyboard Name="ConnectToMe" Duration="0:0:2.5" FillBehavior="Stop">
                                                    <DoubleAnimation To="400" Duration="0:0:1.5" Storyboard.TargetName="IconHighlight1" Storyboard.TargetProperty="Height" FillBehavior="Stop" />
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </DataTrigger.EnterActions>
                                    </DataTrigger>
                                </DataTemplate.Triggers>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

【问题讨论】:

    标签: wpf xaml storyboard datatemplate


    【解决方案1】:

    在这种情况下,我通常希望在您的Storyboard 正在申请的项目的DataContext 中有一个布尔值,并说它是AnimationCompleted

    现在将您的 Storyboard 修改为

    <Storyboard x:Key="ConnectToMe" Duration="0:0:2.5" FillBehavior="Stop">
      <DoubleAnimation To="400" Duration="0:0:1.5" Storyboard.TargetName="IconHighlight1" Storyboard.TargetProperty="Height" FillBehavior="Stop" />
      <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext.AnimationCompleted" FillBehavior="HoldEnd">
        <DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:0" />
      </BooleanAnimationUsingKeyFrames>
      <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext.AnimationCompleted" FillBehavior="HoldEnd">
        <DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:2.5" />
      </BooleanAnimationUsingKeyFrames>
    </Storyboard>
    

    我们在动画结束时将 bool AnimationCompleted 切换为 true。因此在AnimationCompleted 的属性设置器中检查传入的value 是否为True 并从那里触发相应的函数/方法

    【讨论】:

    • 这似乎是一个明智的解决方案,也没有任何复杂的接线逻辑。我仍然会对DataTemplates 如何在后台工作感兴趣,看看是否有更“纯粹”的方式来做到这一点,但这可能更简洁,尤其是在 XAML 中。
    • 好吧,在这种情况下,每个项目都是“基于”包含故事板的 ItemTemplate,这会让我相信就像他们基于模板为每个项目创建的视觉树一样,故事板将是也是如此。如果他们在父级的 DataContext 或父级范围资源中引用故事板,那么他们可能正在“共享”故事板。
    • 就仅保留 xaml 而言,这清楚地将逻辑委托给 MVVM 中的 VM 以完成已完成的操作。因此,只需让 View 执行与 View 相关的工作,并让 VM 处理应用程序逻辑,就像它应该做的那样。将它们进一步混合是我不想做的事情。
    • 您是否遇到过未设置 AnimationCompleted 属性的问题?我已经实现了相同的模式,但它似乎只是间歇性地工作。
    • @StephenHewlett 错了。没有任何问题。您可以将FillBehavior="HoldEnd" 添加到两个布尔动画中,以强制它在动画完成后不切换值,并查看是否可以解决问题。将断点添加到 AnimationCompleted 属性并检查以确保它仅在预期时触发并且不超过预期的次数。
    猜你喜欢
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2014-11-08
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多