简体   繁体   English

不能在 Style Setter 上设置 TargetName 属性,那么它是如何设置的呢?

[英]TargetName property cannot be set on a Style Setter, so how is it set?

I've spent this past week exploring WPF so it's still very new to me.过去一周我一直在探索 WPF,所以它对我来说仍然很陌生。 One of the things I'm working on is simple animations.我正在做的一件事是简单的动画。 In this case a bouncing smiley face.在这种情况下,一个弹跳的笑脸。

My plan of attack is:我的攻击计划是:

  1. Make a smiley face.做个笑脸。 I've done this.我已经这样做了。
  2. Work out the bouncing animation on a simple object.在一个简单的对象上制定弹跳动画。 I've done this.我已经这样做了。
  3. Abstract that animation so it can be used in several places (the elements of the smiley face).抽象该动画,以便它可以在多个地方使用(笑脸的元素)。 I'm stuck here.我被困在这里。
  4. Apply the abstracted animation style to all the elements of the smiley face.将抽象的动画风格应用于笑脸的所有元素。

After step #2 I had the the following working XAML:在第 2 步之后,我有以下工作 XAML:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="Test Window" Height="350" Width="620">
    <Grid>
        <Canvas Margin="0,180,0,0">
            <Ellipse Canvas.Left="10" Canvas.Top="10" Width="100" Height="100" Stroke="Blue" StrokeThickness="4" Fill="Aqua" />
            <Ellipse Canvas.Left="30" Canvas.Top="12" Width="60" Height="30">
                <Ellipse.Fill>
                    <LinearGradientBrush StartPoint="0.45,0" EndPoint="0.5, 0.9">
                        <GradientStop Offset="0.2" Color="DarkMagenta" />
                        <GradientStop Offset="0.7" Color="Transparent" />
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
            <Ellipse Canvas.Left="33" Canvas.Top="35" Width="20" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
            <Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
            <Ellipse Canvas.Left="68" Canvas.Top="35" Width="20" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
            <Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
            <Path Name="mouth" Stroke="Blue" StrokeThickness="4" Data="M 35,75 Q 55,90 80,75 " />
        </Canvas>
        <Grid Margin="100,5,0,0" Width="75" Height="300">
            <Canvas>
                <Ellipse Height="40" Width="40" x:Name="theBall" Canvas.Left="16">
                    <Ellipse.Fill>
                        <RadialGradientBrush GradientOrigin="0.75,0.25">
                            <GradientStop Color="Yellow" Offset="0.0" />
                            <GradientStop Color="Red" Offset="1.0" />
                        </RadialGradientBrush>
                    </Ellipse.Fill>
                    <Ellipse.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform x:Name="aniSquash"/>
                            <TranslateTransform x:Name="aniBounce"/>
                        </TransformGroup>
                    </Ellipse.RenderTransform>
                    <Ellipse.Triggers>
                        <EventTrigger RoutedEvent="Loaded">
                            <BeginStoryboard>
                                <Storyboard SpeedRatio="2.0">
                                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniBounce" Storyboard.TargetProperty="Y" RepeatBehavior="Forever">
                                        <LinearDoubleKeyFrame Value="120" KeyTime="0:0:0"/>
                                        <SplineDoubleKeyFrame Value="260" KeyTime="0:0:2.2" KeySpline="0, 0, 0.5, 0"/>
                                        <LinearDoubleKeyFrame Value="260" KeyTime="0:0:2.25"/>
                                        <SplineDoubleKeyFrame Value="120" KeyTime="0:0:4.5" KeySpline="0, 0, 0, 0.5"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleX" RepeatBehavior="Forever">
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                                        <LinearDoubleKeyFrame Value="1.3" KeyTime="0:0:2.25"/>
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleY" RepeatBehavior="Forever">
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                                        <LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:2.25"/>
                                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Ellipse.Triggers>
                </Ellipse>
                <Rectangle Height="5" Canvas.Left="10" Canvas.Top="285" Width="55" Fill="Black"/>
            </Canvas>
        </Grid>
    </Grid>
</Window>

While altering the above, working, XAML for step #3 I introduced an error I don't really understand.在更改上述内容时,第 3 步的 XAML 工作引入了一个我不太了解的错误。 Here is the altered XAML that doesn't work:这是无效的更改后的 XAML:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="Test Window" Height="350" Width="620">
    <Window.Resources>
        <TransformGroup x:Key="aniBounceAndSquash">
            <ScaleTransform x:Name="aniSquash"/>
            <TranslateTransform x:Name="aniBounce"/>
        </TransformGroup>
        <Style x:Key="styleBounceAndSquash" TargetType="FrameworkElement">
            <Setter Property="RenderTransform" Value="{StaticResource aniBounceAndSquash}" />
            <Style.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard>
                        <Storyboard SpeedRatio="2.0">
                            <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniBounce" Storyboard.TargetProperty="Y" RepeatBehavior="Forever">
                                <LinearDoubleKeyFrame Value="120" KeyTime="0:0:0"/>
                                <SplineDoubleKeyFrame Value="260" KeyTime="0:0:2.2" KeySpline="0, 0, 0.5, 0"/>
                                <LinearDoubleKeyFrame Value="260" KeyTime="0:0:2.25"/>
                                <SplineDoubleKeyFrame Value="120" KeyTime="0:0:4.5" KeySpline="0, 0, 0, 0.5"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleX" RepeatBehavior="Forever">
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                                <LinearDoubleKeyFrame Value="1.3" KeyTime="0:0:2.25"/>
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleY" RepeatBehavior="Forever">
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                                <LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:2.25"/>
                                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Canvas Margin="0,180,0,0">
            <Ellipse Canvas.Left="10" Canvas.Top="10" Width="100" Height="100" Stroke="Blue" StrokeThickness="4" Fill="Aqua" />
            <Ellipse Canvas.Left="30" Canvas.Top="12" Width="60" Height="30">
                <Ellipse.Fill>
                    <LinearGradientBrush StartPoint="0.45,0" EndPoint="0.5, 0.9">
                        <GradientStop Offset="0.2" Color="DarkMagenta" />
                        <GradientStop Offset="0.7" Color="Transparent" />
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
            <Ellipse Canvas.Left="33" Canvas.Top="35" Width="20" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
            <Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
            <Ellipse Canvas.Left="68" Canvas.Top="35" Width="20" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White" />
            <Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black" />
            <Path Name="mouth" Stroke="Blue" StrokeThickness="4" Data="M 35,75 Q 55,90 80,75 " />
        </Canvas>
        <Grid Margin="100,5,0,0" Width="75" Height="300">
            <Canvas>
                <Ellipse Height="40" Width="40" x:Name="theBall" Canvas.Left="16" Style="{StaticResource styleBounceAndSquash}">
                    <Ellipse.Fill>
                        <RadialGradientBrush GradientOrigin="0.75,0.25">
                            <GradientStop Color="Yellow" Offset="0.0" />
                            <GradientStop Color="Red" Offset="1.0" />
                        </RadialGradientBrush>
                    </Ellipse.Fill>
                </Ellipse>
                <Rectangle Height="5" Canvas.Left="10" Canvas.Top="285" Width="55" Fill="Black"/>
            </Canvas>
        </Grid>
    </Grid>
</Window>

The error "TargetName property cannot be set on a Style Setter. Line 20 Position 79."错误“无法在样式设置器上设置 TargetName 属性。第 20 行位置 79。”

If I can't set it in the style how do I set it?如果我不能在样式中设置它,我该如何设置?

Well it turns out that you can't set Storyboard.TargetName in a Style.Setter because it's a style and is abstracted.事实证明,您不能在Style.Setter设置Storyboard.TargetName ,因为它是一种样式并且是抽象的。 Hence a reference via name is not allowed as "there is no spoon".因此,不允许通过名称进行引用,因为“没有勺子”。 So I dropped Storyboard.TargetName and looked for another way.所以我放弃了Storyboard.TargetName并寻找另一种方式。

I did find that in Storyboard.TargetProperty you can use the object structure, sort of like walking the DOM, to reference the object you want.我确实发现在Storyboard.TargetProperty你可以使用对象结构,有点像遍历 DOM,来引用你想要的对象。 In that way you bypass the need for Storyboard.TargetName .通过这种方式,您可以绕过Storyboard.TargetName的需要。 It took longer to work out referencing the object by structure because I was using a TransformGroup and MS docs are not the most friendly of docs.由于我使用的是TransformGroup并且 MS 文档不是最友好的文档,因此按结构引用对象需要更长的时间。 Finally, I got it and here it is for anyone else that has the same problem.最后,我得到了它,它适用于其他有同样问题的人。

<Style x:Key="buttonSmiley" TargetType="{x:Type Button}">
    <Style.Resources>
        <Storyboard x:Key="OnVisibleStoryboard">
            <DoubleAnimationUsingKeyFrames Duration="0:0:2.75" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)" >
                <LinearDoubleKeyFrame Value="75" KeyTime="0:0:0"/>
                <SplineDoubleKeyFrame Value="25" KeyTime="0:0:0.75" KeySpline="0, 0, 0.5, 0"/>
                <LinearDoubleKeyFrame Value="-25" KeyTime="0:0:1.2"/>
                <SplineDoubleKeyFrame Value="200" KeyTime="0:0:2.25" KeySpline="0, 0, 0, 0.5"/>
                <LinearDoubleKeyFrame Value="175" KeyTime="0:0:2.4" />
                <SplineDoubleKeyFrame Value="150" KeyTime="0:0:2.75" KeySpline="0, 0, 0, 0.5"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Duration="0:0:5.5" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleX)" >
                <LinearDoubleKeyFrame Value="0.01" KeyTime="0:0:0"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:1.25"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.05"/>
                <LinearDoubleKeyFrame Value="1.15" KeyTime="0:0:2.15"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.4"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.75"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Duration="0:0:5.5" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleY)" >
                <LinearDoubleKeyFrame Value="0.01" KeyTime="0:0:0"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:1.25"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.05"/>
                <LinearDoubleKeyFrame Value="0.75" KeyTime="0:0:2.2"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.4"/>
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.75"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Style.Resources>
    <Style.Triggers>
        <Trigger Property="Visibility" Value="Visible">
            <Trigger.EnterActions>
                <RemoveStoryboard BeginStoryboardName="OnLoadStoryboard_BeginStoryboard"/>
                <BeginStoryboard x:Name="OnVisibleStoryboard_BeginStoryboard" Storyboard="{StaticResource OnVisibleStoryboard}"/>
            </Trigger.EnterActions>
        </Trigger>
        <EventTrigger RoutedEvent="Button.Loaded">
            <RemoveStoryboard BeginStoryboardName="OnVisibleStoryboard_BeginStoryboard"/>
            <BeginStoryboard x:Name="OnLoadStoryboard_BeginStoryboard" Storyboard="{StaticResource OnVisibleStoryboard}"/>
        </EventTrigger>
    </Style.Triggers>
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Canvas Margin="-35,-35,0,0">
                    <Ellipse Canvas.Left="10" Canvas.Top="10" Width="50" Height="50" Stroke="Blue" StrokeThickness="2" Fill="#FFD8CF15" />
                    <Ellipse Canvas.Left="18" Canvas.Top="12" Width="33" Height="15">
                        <Ellipse.Fill>
                            <LinearGradientBrush StartPoint="0.45,0" EndPoint="0.5, 0.9">
                                <GradientStop Offset="0.2" Color="DarkMagenta" />
                                <GradientStop Offset="0.7" Color="Transparent" />
                            </LinearGradientBrush>
                        </Ellipse.Fill>
                    </Ellipse>
                    <Ellipse Canvas.Left="17" Canvas.Top="25" Width="10" Height="10" Stroke="Blue" StrokeThickness="2" Fill="White" />
                    <Ellipse Canvas.Left="20" Canvas.Top="28" Width="3" Height="3" Fill="Black" />
                    <Ellipse Canvas.Left="34" Canvas.Top="25" Width="10" Height="10" Stroke="Blue" StrokeThickness="2" Fill="White" />
                    <Ellipse Canvas.Left="37" Canvas.Top="28" Width="3" Height="3" Fill="Black" />
                    <Path Name="mouth" Stroke="Blue" StrokeThickness="2" Data="M 20,43 Q 27,53 40,44" />
                </Canvas>
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="RenderTransform">
        <Setter.Value>
            <TransformGroup>
                <TranslateTransform />
                <ScaleTransform />
            </TransformGroup>
        </Setter.Value>
    </Setter>
</Style>

Of course I would have given up on the style altogether if Button.Triggers would have allowed normal triggers and not JUST event triggers in the collection, thank you MS for making life painful, er um I mean fun.当然,如果Button.Triggers允许正常触发器而不是集合中的 JUST 事件触发器,我会完全放弃这种样式,谢谢 MS 让生活变得痛苦,呃,我的意思是有趣。 Because I needed both I had to work this out.因为我需要两者,所以我必须解决这个问题。

I had this issue because I was building a custom resource (a button).我遇到这个问题是因为我正在构建一个自定义资源(一个按钮)。

This was my problem, and its solution:这是我的问题,及其解决方案:

<Style x:Key="MyButton" TargetType="{x:Type Button}">
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                ...
                <ControlTemplate.Triggers>
                    ==> should have put triggers here <==
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        ==> not here <==
    </Style.Triggers>
</Style>

Here is an example of your animation applied to a Button .这是应用于Button动画示例。 Its probably not quite the answer you're looking for as it does not have reusable resources.它可能不是您正在寻找的答案,因为它没有可重用的资源。 I have just moved the TransformGroup , Trigger and Storyboard into the control.我刚刚将TransformGroupTriggerStoryboard移到了控件中。 I will take another look...我再看看...

<Button Style="{StaticResource styleBounceAndSquash}">
    <Button.RenderTransform>
        <TransformGroup>
            <ScaleTransform x:Name="aniSquash"/>
            <TranslateTransform x:Name="aniBounce"/>
        </TransformGroup>
    </Button.RenderTransform>
    <Button.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard SpeedRatio="2.0">
                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniBounce" Storyboard.TargetProperty="Y" RepeatBehavior="Forever">
                        <LinearDoubleKeyFrame Value="120" KeyTime="0:0:0"/>
                        <SplineDoubleKeyFrame Value="260" KeyTime="0:0:2.2" KeySpline="0, 0, 0.5, 0"/>
                        <LinearDoubleKeyFrame Value="260" KeyTime="0:0:2.25"/>
                        <SplineDoubleKeyFrame Value="120" KeyTime="0:0:4.5" KeySpline="0, 0, 0, 0.5"/>
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleX" RepeatBehavior="Forever">
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                        <LinearDoubleKeyFrame Value="1.3" KeyTime="0:0:2.25"/>
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="aniSquash" Storyboard.TargetProperty="ScaleY" RepeatBehavior="Forever">
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2"/>
                        <LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:2.25"/>
                        <LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM