The TargetName property cannot be set in the Style Setter, so how is it set?

I spent studying WPF last week, so this is still very much for me. One of the things I'm working on is simple animations. In this case, the bouncing smiley face.

My attack plan:

  • Make a smiley. I have done it.
  • Design bouncing animations on a simple object. I have done it.
  • Abstract animation, so it can be used in several places (emoticon elements). I'm stuck here.
  • Apply an abstract animation style to all elements of emoticons.

After step # 2, I had the following working 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> 

When changing the above, while working, XAML for step number 3, I introduced an error that I really do not understand. Here is the modified XAML that does not work:

 <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> 

Error "TargetName property could not be set in Style Setter. Line 20 Position 79."

If I can’t install it in style, how to install it?

+6
source share
2 answers

Well, it turns out that you cannot set Storyboard.TargetName to Style.Setter because it is style and abstracts. Therefore, the link through the name is not allowed, as "no spoon." So I dropped Storyboard.TargetName and looked for another way.

I found that in Storyboard.TargetProperty you can use the structure of an object, sort of like going around the DOM to refer to the object you want. This way you get around the need for a Storyboard.TargetName . It took more time to refer to the object by structure, because I used TransformGroup , and MS documents are not the most friendly documents. Finally, I got it, and here it is for someone else 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 completely abandon the style if Button.Triggers would allow ordinary triggers, and not JUST event triggers in the collection, thanks to MS for making your life painful, uh, I mean fun. Because I needed both, I had to fix it.

+8
source

Here is an example of your animation applied to Button . This is probably not exactly the answer you are looking for since it does not have reusable resources. I just moved TransformGroup , Trigger and Storyboard to the control. I'll see it again ...

 <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> 
+1
source

All Articles