WPF:选择动画的目标

Phi*_*ler 5 data-binding wpf animation

我试图根据我的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>
Run Code Online (Sandbox Code Playgroud)

更新

还应该提到我试图命名TextBlock并通过StoryBoard.TargetName引用它(正如Timores建议的那样),并得到错误"无法在Style Setter上设置TargetName属性".

geh*_*hho 5

编辑:我有监督的事实,TextBlock就是在ControlTemplate您的自定义窗口/控制.我不认为这是有可能的目标控制范围内ControlTemplateStoryboard 外面的这个ControlTemplate.你可以在你的自定义窗口然而定义属性,你那么数据绑定到你的ChangeOccurred属性,然后触发添加到您ControlTemplate现在将获得由定制控件的属性触发,而不是窗口的视图模型的财产(当然,间接地是由触发ViewModel因为ChangeOccurred绑定到自定义Window的属性,而后者又触发动画 - 呃,复杂的句子,希望你理解.这是一个选择吗?你能跟着吗?;-)

也许一些代码有帮助:

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

    public bool ChangeOccurred2 { ... }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

还有一些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>
Run Code Online (Sandbox Code Playgroud)

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


我的回答是:

那么,你想要动画TextBlock一个(自定义)窗口的内容?!

为什么要在窗口上设置样式,而不是在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>
Run Code Online (Sandbox Code Playgroud)

{Binding ChangeOccurred}可能是不够的.您可能需要一个补充DataContextTextBlock,或添加RelativeSource什么的.