I need a small square inside a Canvas to be animated depending on View-Model's properties, here's XAML
<Style x:Key="FlashingRectStyle">
<Style.Triggers>
<!-- HasPath & IsBig -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="20" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="20" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="190" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="30" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="115" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="35" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
</MultiDataTrigger>
<!-- HasPath & Not IsBig -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="77" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="73" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="138" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="57" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="97" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="53" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
</MultiDataTrigger>
<!-- Not HasPath-->
<DataTrigger Binding="{Binding Path=HasPath}" Value="False">
<Setter Property="Canvas.Left" Value="105" />
<Setter Property="Canvas.Top" Value="75" />
</DataTrigger>
</Style.Triggers>
</Style>
And usage
<Canvas>
<Rectangle Style="{StaticResource FlashingRectStyle}" Width="30" Height="20" />
</Canvas>
The defaults for HasPath and IsBig are both True and the first animation block "HasPath & IsBig" animates correct.
Also if I change IsBig to false "HasPath & Not IsBig" does begin animating. But if I then change back IsBig to true - nothing happens and "HasPath & Not IsBig" keeps animating. Also if I set HasPath to false it should fire "Not HasPath" but it doesn't. How do I make it switch animation on fly when properties changed?
You need to remove the previous storyboard in the ExitActions before adding a new one:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard x:Name="BeginStoryboardName">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="77" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="73" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="138" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)"
Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="57" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="97" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="53" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="BeginStoryboardName"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
Related
I'm trying to make a MultiTrigger condition but I need change this condition based on the TextBlock Tag, if the Tag=0 run the first trigger and if Tag=1 run the another one. But in my code if the trigger condition where the Tag=0 ran and thereafter the Tag is changed to 1 the other trigger won't run.
I'm using this code:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="#FF333333"/>
<Setter Property="Foreground" Value="#FFBEBEBE"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Tag" Value="0"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.300" />
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="Black" Duration="0:0:0.300" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FFF0F2F3" Duration="0:0:0.300" />
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="Black" Duration="0:0:0.300" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Tag" Value="1"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#222222" Duration="0:0:0.300" />
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="#FFFFFF" Duration="0:0:0.300" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF333333" Duration="0:0:0.300" />
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="#FFBEBEBE" Duration="0:0:0.300" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</Style.Triggers>
</Style>
Some one knows what is wrong with this code? Or maybe it's possible.
In my application I have a lot of very large DataGridTemplateColumn-Definitions. For each column I'm defining a style. The style for example of two columns looks like:
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource BaseDataGridCellStyle}">
<Setter Property="IsEditing"
Value="{Binding CurrentEditTarget, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
Converter={converters:EditConverter}, ConverterParameter={x:Static component:EditTarget.VariantPath}}" />
<Setter Property="BorderBrush" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentEditTarget}" Value="{x:Static component:EditTarget.VariantPath}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="(Border.BorderThickness)" FillBehavior="HoldEnd" From="4" To="0" Duration="0:0:0.5" >
<ThicknessAnimation.EasingFunction>
<PowerEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetProperty="(Border.Margin)" FillBehavior="HoldEnd" From="-20,0,20,0" To="0" Duration="0:0:0.5" >
<ThicknessAnimation.EasingFunction>
<PowerEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<Setter Property="attachedProperties:DataGridExtensions.FocusOnEditingColumn" Value="VariantPath"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
-
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource BaseDataGridCellStyle}">
<Setter Property="IsEditing"
Value="{Binding CurrentEditTarget, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
Converter={converters:EditConverter}, ConverterParameter={x:Static component:EditTarget.OriginalPath}}" />
<Setter Property="BorderBrush" Value="Blue" />
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentEditTarget}" Value="{x:Static component:EditTarget.OriginalPath}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="(Border.BorderThickness)" FillBehavior="HoldEnd" From="4" To="0" Duration="0:0:0.5" >
<ThicknessAnimation.EasingFunction>
<PowerEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetProperty="(Border.Margin)" FillBehavior="HoldEnd" From="-20,0,20,0" To="0" Duration="0:0:0.5" >
<ThicknessAnimation.EasingFunction>
<PowerEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<Setter Property="attachedProperties:DataGridExtensions.FocusOnEditingColumn" Value="OriginalPath"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
I was wondering if there is a way to extract the Storyboard into a style or resource or something else. Because this is the part of the style which is always the same for each DataGridTemplateColumn
How about this:
<Application.Resources>
<Storyboard x:Key="SB_Height" x:Shared="False">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)"
Storyboard.TargetName="{DynamicResource AnimationTarget}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Application.Resources>
<Button Name="mybutton" Content="Test" Height="20">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource SB_Height}"/>
</EventTrigger>
</Button.Triggers>
</Button>
I have the following xaml
<DataGrid Name ="TheGrid" Margin="0,21,0,0" DataContext ="{Binding StreamItems}" ItemsSource="{Binding}" CanUserReorderColumns="True" CanUserResizeColumns="True"
CanUserResizeRows="False" CanUserSortColumns="True" AutoGenerateColumns="False" RowHeight="21">
<DataGrid.Resources>
<Style TargetType="DataGridCell" x:Key="FlashStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentState}" Value="Idle" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="BlinkIdle" >
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<DiscreteColorKeyFrame Value="DarkOrchid" KeyTime="0:0:0" />
<DiscreteColorKeyFrame Value="DarkOrchid" KeyTime="0:0:5" />
<LinearColorKeyFrame Value="Transparent" KeyTime="0:0:8" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentState}" Value="Streaming" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="BlinkStreaming">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<DiscreteColorKeyFrame Value="DarkGreen" KeyTime="0:0:0" />
<DiscreteColorKeyFrame Value="DarkGreen" KeyTime="0:0:5" />
<LinearColorKeyFrame Value="Transparent" KeyTime="0:0:8" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
The problem i'm having, is when i scroll, or the user sorts columns, the animation is triggers. how do i tell the animation to trigger only once, when the data changes?
I have the following XAML for a "toaster" popup:
<Popup x:Name="popupMessage"
Width="500"
Height="100"
IsOpen="False"
Placement="Top"
PlacementTarget="{Binding ElementName=statusBarMain}"
StaysOpen="True">
<Popup.Style>
<Style>
<Style.Triggers>
<Trigger Property="Popup.IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="0" />
</DoubleAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
<DiscreteBooleanKeyFrame KeyTime="0:0:4" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Popup.Style>
<Popup.RenderTransform>
<ScaleTransform ScaleY="1" />
</Popup.RenderTransform>
<Border Width="504"
Height="104"
BorderBrush="#FF0F3D5C"
BorderThickness="2">
<Border Width="500"
Height="100"
BorderBrush="White"
BorderThickness="2">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFD3CCF5" />
<GradientStop Offset="1" Color="#FF0F3D5C" />
</LinearGradientBrush>
</Border.Background>
<TextBlock x:Name="textBlockMessage"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="18"
Foreground="White"
Text="{Binding NotificationMessage}" />
</Border>
</Border>
</Popup>
The problem with this Popup is that it only seems to work once. I set popupMessage.IsOpen = true and this shows the popup one time. All subsequent calls don't let the popup appear. I checked and the IsOpen property is indeed set to false at the end of the animation.
Clearly I'm missing something here, but what?
You need to stop your storyboard in the ExitActions of your Trigger.
Try this:
<Trigger Property="Popup.IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Name="OpenStoryboard">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="0" />
</DoubleAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
<DiscreteBooleanKeyFrame KeyTime="0:0:4" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="OpenStoryboard"/>
</Trigger.ExitActions>
</Trigger>
I had a similar issue when changing the background colour of a control using an animation and it would also only work once.
I have a rectangle, and I have a storyboard:
<Storyboard x:Key="PressAndHoldColorBar">
<ColorAnimationUsingKeyFrames Duration="0:0:10" FillBehavior="Stop" Storyboard.TargetName="rectWarning" Storyboard.TargetProperty="Fill">
<LinearColorKeyFrame KeyTime="0:0:0" Value="Green" />
<LinearColorKeyFrame KeyTime="0:0:7" Value="Yellow" />
<LinearColorKeyFrame KeyTime="0:0:10" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Rectangle Height="100" HorizontalAlignment="Left" Margin="12,328,0,0" Name="rectWarning" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="200">
I want this color change to occur when another button is pressed, so I'm trying to call the code programmatically:
s = (Storyboard)this.Resources["PressAndHoldColorBar"];
s.Begin();
I've narrowed it down to Storyboard.TargetName and TargetProperty in the first snippet (I think). I just need help figuring out what to do to get it to work completely.
Figured it out:
<Storyboard x:Name="PressAndHoldColorBar">
<ColorAnimationUsingKeyFrames Duration="0:0:10" FillBehavior="Stop" Storyboard.TargetName="rectWarning"
Storyboard.TargetProperty="(Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="0:0:0" Value="Green" />
<LinearColorKeyFrame KeyTime="0:0:7" Value="Yellow" />
<LinearColorKeyFrame KeyTime="0:0:10" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
You have to use (Fill).(SolidColorBrush.Color). It doesn't like (Shape.Fill).