【问题标题】:WPF: Selecting the Target of an AnimationWPF:选择动画的目标
【发布时间】:2010-04-29 20:24:04
【问题描述】:

我正在尝试根据我的 ViewModel 中的属性更改创建一个简单的(我认为)动画效果。我希望目标是自定义控件的控件模板中的特定文本块,它继承自 Window。

从我看到的文章示例中,DataTrigger 是完成此任务的最简单方法。 Window.Triggers 似乎不支持 DataTriggers,这导致我尝试在样式中应用触发器。我目前遇到的问题是我似乎无法定位 TextBlock(或任何其他子控件)——下面的代码是将动画应用于整个窗口的背景。

如果我完全离开 StoryBoard.Target,效果完全一样。

这是使用错误语法的正确方法,还是有更简单的方法来完成此操作?

<Style x:Key="MyWindowStyle" TargetType="{x:Type Window}">
    <Setter Property="Template" Value="{StaticResource MyWindowTemplate}"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding ChangeOccurred}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard BeginTime="00:00:00" Duration="0:0:2" Storyboard.Target="{Binding RelativeSource={RelativeSource AncestorType=TextBlock}}"
                                    Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                        <ColorAnimation FillBehavior="Stop" From="Black" To="Red" Duration="0:0:0.5" AutoReverse="True"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

更新

还应该提到我尝试命名 TextBlock 并通过 StoryBoard.TargetName 引用它(正如 Timores 建议的那样),并收到错误“TargetName 属性无法在样式设置器上设置。”

【问题讨论】:

  • 您想要的动画目标到底是什么?您说“自定义控件的控件模板中的特定文本块”,然后为Window 而不是自定义控件创建样式。你能提供包含你的动画目标的代码吗?上面的目标绑定不应该工作,因为我不希望 Window 有一个 TextBlock 类型的祖先,是吗?!这可能吗?
  • 抱歉,这是一个难以描述的设置。自定义控件一个窗口,因为它派生自 window。设置/样式是由其他人创建的,所以我正在尝试改造这个动画。 Textblock 是一个子控件——再看一遍,RelativeSource/AncestorType 可能还没有接近,因为我试图定位一个孩子而不是父母?

标签: wpf data-binding animation


【解决方案1】:

编辑:我发现TextBlock 位于您的自定义窗口/控件的ControlTemplate 中。我认为不可能从StoryboardControlTemplate inside 定位ControlTemplate 的控件inside。但是,您可以在自定义 Window 上定义一个属性,然后将其数据绑定到您的 ChangeOccurred 属性,然后将触发器添加到您的 ControlTemplate 现在将由自定义控件的属性而不是 Window 的 ViewModel 属性触发(当然, 间接是由 ViewModel 触发的,因为ChangeOccurred 绑定到自定义 Window 的属性,进而触发动画 - 呃,复杂的句子,希望你理解)。这是一个选项吗?你能跟上吗? ;-)

也许一些代码会有所帮助:

public class MyCustomWindow : Window
{
    public static readonly DependencyProperty ChangeOccurred2 = DependencyProperty.Register(...);

    public bool ChangeOccurred2 { ... }

    // ...
}

还有一些 XAML:

<local:MyCustomWindow ChangeOccurred2="{Binding ChangeOccurred}" ... >
    <!-- Your content here... -->
</local:MyCustomWindow>

<!-- Somewhere else (whereever your ControlTemplate is defined) -->
<ControlTemplate TargetType="{x:Type local:MyCustomWindow}">

    <!-- your template here -->

    <ControlTemplate.Triggers>
        <Trigger Property="ChangeOccurred2" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard BeginTime="00:00:00" Duration="0:0:2"
                                Storyboard.TargetName="txtWhatever"
                                Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                        <ColorAnimation FillBehavior="Stop"
                                        From="Black" To="Red"
                                        Duration="0:0:0.5"
                                        AutoReverse="True"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

注意:我将 Window 的属性命名为 ChangeOccurred2,因为我希望它与 ViewModel 的 ChangeOccurred 属性区分开来。当然,您应该为该属性选择一个更好的名称。但是,我错过了做出这样一个决定的背景。


我的旧答案:

那么,您想为(自定义)窗口内容中的TextBlock 设置动画?!

为什么要在 Window 上设置样式,而不是在 TextBlock 本身上?也许你应该尝试这样的事情(没有测试这个!):

<local:MyCustomWindow ... >
    <!-- ... -->
    <TextBlock x:Name="textBlockAnimated" ... >
        <TextBlock.Style>
            <Style TargetType="{x:Type TextBlock}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ChangeOccurred}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard BeginTime="00:00:00" Duration="0:0:2"
                                            Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                                    <ColorAnimation FillBehavior="Stop"
                                                    From="Black" To="Red"
                                                    Duration="0:0:0.5"
                                                    AutoReverse="True"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
    <!-- ... -->
</local:MyCustomWindow>

{Binding ChangeOccurred} 可能不够用。您可能需要在TextBlock 中添加DataContext,或添加RelativeSource 或其他内容。

【讨论】:

  • 您更新的答案有效!谢谢你的帮助。我觉得我接近它的方式是倒退的,但我对 WPF 中的样式/动画非常陌生。
【解决方案2】:

是 MyWindowTemplate 中的 TextBlock 吗?

如果是这样,请给 TextBlock 一个名称并使用 Storyboard.TargetName 来引用它。

another question in SO

【讨论】:

  • 对不起,应该提到我尝试过并得到:“TargetName 属性不能在样式设置器上设置。”
  • 另外:是的,它在控件模板中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多