WPF MultiDataTrigger.EnterAction is not working with a custom attribute - c#

I've been trying to get a WPF multi datatrigger to work on triggering a storyboard animation on a customized ToggleButton based of this control http://marcangers.com/animated-switch-togglebutton-style-in-wpf/ . The toggle button is an extension of a regular WPF ToggleButton with a custom attribute of Status which will either show as Modified or Unmodified. My MultiDataTrigger is triggering on whether the togglebutton IsChecked and the status is either modified or unmodified. The problem is, the storyboards aren't triggering at all. When I have the storyboard animations in a regular trigger it works just fine. Here's the custom toggle button.
CustomToggleButton.xaml
<ToggleButton x:Class="DPC9600CustomControlLibrary.CustomToggleButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ControlLibrary"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ToggleButton.Resources>
<ResourceDictionary Source="Themes/Styles_CustomToggleButton.xaml"/>
</ToggleButton.Resources>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource CustomToggleButton}"/>
</ToggleButton.Style>
</ToggleButton>
CustomToggleButton.xaml.cs
public partial class CustomToggleButton : ToggleButton
{
public static readonly DependencyProperty StatusProperty =
DependencyProperty.Register("Status", typeof(ConfigurationValueStatus), typeof(CustomToggleButton));
public ConfigurationValueStatus Status
{
get { return (ConfigurationValueStatus) GetValue(StatusProperty); }
set { SetValue(StatusProperty, value); }
}
public CustomToggleButton()
{
InitializeComponent();
}
}
And here's my multidata triggers in Styles_CustomToggleButton.xaml
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding Status,ElementName=Myself}" Value="Unmodified"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF377EC1" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#FF377EC1" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="15" KeySpline="0, 1, 0.6, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FAFAFB" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#EAEAEB" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="15"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0" KeySpline="0, 0.5, 0.5, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding Status,ElementName=Myself}" Value="Modified"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Goldenrod" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="Goldenrod" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="15" KeySpline="0, 1, 0.6, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FAFAFB" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#EAEAEB" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="15"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0" KeySpline="0, 0.5, 0.5, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
I'm not sure what I'm doing wrong, using a regular trigger makes the animation work. Here's a look at the trigger.
<Trigger Property="IsChecked" Value="true" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF377EC1" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#FF377EC1" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="15" KeySpline="0, 1, 0.6, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FAFAFB" Duration="0:0:0.2" />
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#EAEAEB" Duration="0:0:0.2" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0" Value="15"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0" KeySpline="0, 0.5, 0.5, 1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>

I can't find a definition for Myself in your XAML.
If this is in Style.Triggers (I'm pretty sure it is), I would think the binding to Status should be {Binding Status, RelativeSource={RelativeSource Self}, just like your IsChecked binding.
If I'm wrong and it's in ControlTemplate.Triggers, I would try {Binding Status, RelativeSource={RelativeSource TemplatedParent} -- and the same for IsChecked.

The problem was with <Condition Binding="{Binding Status,ElementName=Myself}" Value="Modified"/> all I had to do was switch it to <Condition Binding="{Binding Status, RelativeSource={RelativeSource=Self}}" Value="Modified"/>
This change fixes the styling triggers.

Related

Animation lost when clicking on DataGrid

I have a DataGrid which contains a list of item that implement a boolean property called ResultChanged, this property allow me to create a blink effect on a particular cell of the DataGrid, in particular, if the property is setted to true then the cell of the DataGrid will colored by orange and blinking for 5 seconds, at the end of the animation, the color will keeped on the DataGrid and this working well for me, except for one problem.
Problem
When I click on the DataGrid (any rows) the color applied by the animation will be removed, but I want that such color remain on the cell.
This is my code:
<DataGridTextColumn Header="{DynamicResource hour}" Binding="{Binding Result}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource MaterialDesignDataGridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<Storyboard x:Name="Blink"
AutoReverse="True"
RepeatBehavior="5x">
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01"
Value="Orange" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01"
Value="Black" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Storyboard AutoReverse="False">
<ColorAnimationUsingKeyFrames BeginTime="00:00:10" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01" Value="Orange" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
someone know what I did wrong?
The animation's effects will be lost when you select or unselect the row affected by the animation, because DataGrid changes the foreground and background brushes of the selected row. Now, normally, the animation's changes to the Foreground and Background properties would have precedence over those changes for the selected row.
But your animation does not animate Foreground and Background! Instead, it animates Foreground.Color and Background.Color; these changes have no precedence and will be lost when something else changes Foreground or Background directly.
Therefore, your animation must animate Foreground and Background directly. Then, the changes will remain in effect even after the animation has ended.
You could achieve this, for example, by using the BrushAnimation class from the answer in question Brush to Brush Animation and using a storyboard similar to this:
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<Storyboard x:Name="Blink"
RepeatBehavior="5x">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:0.5" From="White" To="Orange" />
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:0.5" From="Yellow" To="Black" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
EDIT:
Here is a solution that allows AutoReverse to be set to true:
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- The next two animations will take 10 seconds: -->
<Storyboard x:Name="Blink" AutoReverse="True" RepeatBehavior="5x">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
</Storyboard>
<!-- Same animations as above, but BeginTime offset by 10 seconds and neither repeat nor auto reverse: -->
<Storyboard x:Name="finalBlink" BeginTime="00:00:10">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>

Move UserControl in StoryBoard

In my application I have the following XAML-Code to animate the SearchInputView a bit.
<Grid Grid.Row="1" HorizontalAlignment="Right" Grid.RowSpan="4" Panel.ZIndex="200" VerticalAlignment="Top"
Margin="0,-29,6,0">
<Grid.Resources>
<Duration x:Key="SearchAnimationDuration">0:0:0.4</Duration>
<system:Double x:Key="Hidden">0.0</system:Double>
<system:Double x:Key="Visible">1.0</system:Double>
<system:Double x:Key="Transparent">0.5</system:Double>
<Style TargetType="{x:Type view:SearchInputView}">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="{StaticResource Hidden}" To="{StaticResource Visible}"
Duration="{StaticResource SearchAnimationDuration}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="{StaticResource Transparent}" To="{StaticResource Visible}"
Duration="{StaticResource SearchAnimationDuration}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="{StaticResource Visible}" To="{StaticResource Transparent}"
Duration="{StaticResource SearchAnimationDuration}"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<view:SearchInputView Visibility="{Binding DataContext.SearchIsVisible, Mode=TwoWay, Converter={converter:BoolToVisibilityConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</Grid>
The SearchInputView is located in right upper corner of my window. Now I want the control, if the mouse is not over, to fade out of the screen a bit so that only the half of the control is in the visible area. I tried it with the following DoubleAnimation in the ExitActions:
<DoubleAnimation Storyboard.TargetProperty="Margin.Left" To="50" Duration="0:0:0.4"/>
Now when the mouse leaves the control my application crashed immediately.
How can I move my control when the mouse leaves it?
Margin.Left is not DependencyProperty so you cannot animate only left. You can either use ThicknessAnimation to animate whole margin or use TranslateTransform as RenderTransform and animate that
<Style TargetType="{x:Type view:SearchInputView}">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="0" Y="0"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="{StaticResource Transparent}" To="{StaticResource Visible}" Duration="{StaticResource SearchAnimationDuration}"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.X" To="0" Duration="0:0:0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="{StaticResource Visible}" To="{StaticResource Transparent}" Duration="{StaticResource SearchAnimationDuration}"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.X" To="50" Duration="0:0:0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>

Two storyboards .. Same event .. Same property

How to change respectively between two storyboards within the same ex. MouseDown event or button Click event targeting same property ex. visibility.
1st click -> Visibility from 1 to 0 ( Fade Out )
2nd click -> Visibility from 0 to 1 ( Fade In )
3rd click -> Visibility from 1 to 0 ( Fade Out )
4th click -> Visibility from 0 to 1 ( Fade In )
and so on ...
Fade In
<Style TargetType="{x:Type FrameworkElement}" x:Key="FadeIn">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard >
<Storyboard>
<DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
Fade Out
<Style TargetType="{x:Type FrameworkElement}" x:Key="FadeOut">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard >
<Storyboard>
<DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
Thanks in advance,
I think a toggle button is the appropriate control for this, but if you need to use a normal button for whatever reason, use two of them instead of one:
<Window
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:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" mc:Ignorable="d"
x:Class="TestBed.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="Hide_Border">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Btn_Show">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Btn_Hide">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Show_Border">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Btn_Show">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Btn_Hide">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="Btn_Hide">
<BeginStoryboard Storyboard="{StaticResource Hide_Border}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="Btn_Show">
<BeginStoryboard x:Name="Show_Border_BeginStoryboard" Storyboard="{StaticResource Show_Border}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="0.8*"/>
</Grid.ColumnDefinitions>
<Button x:Name="Btn_Hide" Content="Hide" VerticalAlignment="Top"/>
<Button x:Name="Btn_Show" Content="Show" VerticalAlignment="Top" Visibility="Collapsed"/>
<Border x:Name="border" Grid.Column="1" Background="Red" />
</Grid>

Storyboard inside of a DataTrigger not triggering more than once on RaisePropertyChanged event

I am using the MVVM model.
I have a dependency property, a boolean, called "ResultOfUpdate". It is changed whenever a user tries to run a command.
In the setter for this dependency property I am calling "RaisePropertyChanged()" method on the property name.
It is bound to a DataTrigger like so :
<DataTrigger Binding="{Binding ResultOfUpdate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Opacity)"
AutoReverse="True">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.1" Value="0.1"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.2" Value="0.2"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.3" Value="0.3"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.4" Value="0.4"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.5" Value="0.5"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.6" Value="0.6"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.7" Value="0.7"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.8" Value="0.8"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.9" Value="0.9"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
...
<TextBlock Style="{StaticResource statusStyle}"
Opacity="0" Text="Results updated!"
FontSize="10" FontFamily="Segoe UI"/>
I would like for each time this bool is set to true, the storyboard is played.
Confusingly, this storyboard is then triggered correctly the first time the user runs the command, updating the dependecy property to true.
Subsequent attempts have found that the dependency property setter code is entered, and the RaisePropertyChanged() method called - but the storyboard is not played again.
What have I done incorrectly here ?
You could possibly use an event trigger like this:
<StackPanel>
<TextBlock Text="I'm a text block" Name="theTextBlock"/>
<Button Name="BeginButton">Begin</Button>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="theTextBlock"
Storyboard.TargetProperty="(TextBlock.Opacity)"
From="0.0" To="1.0" AutoReverse="True" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>

Multiple DataTriggers - Storyboard overriden

I have two DataTriggers binded to a property (Side) but only one storyboard could be started (the one in the last DataTriggers).
Why ?
I feel like the last storyboard override the first one
<Border x:Name="layout" Background="Transparent" BorderBrush="#BAC8CE" BorderThickness="1" CornerRadius="5">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Side}" Value="Up">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:01"
From="Transparent"
To="Green"/>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Green"
To="Transparent"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Side}" Value="Down">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:01"
From="Transparent"
To="Red"/>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Red"
To="Transparent"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
I would suggest stopping your storyboard before the other one runs:
<Border x:Name="layout" Background="Transparent" BorderBrush="#BAC8CE" BorderThickness="1" CornerRadius="5">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Side}" Value="Up">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="BeginStoryboardTwo" />
<BeginStoryboard x:Name="BeginStoryboardOne">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:01"
From="Transparent"
To="Green"/>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Green"
To="Transparent"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Side}" Value="Down">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="BeginStoryboardOne" />
<BeginStoryboard x:Name="BeginStoryboardTwo" >
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:01"
From="Transparent"
To="Red"/>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Red"
To="Transparent"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="Hello World!" />
</Border>
try following solution, put your second datatrigger enter action at the first datatrigger exit action
<Border x:Name="layout"
Grid.Row="1"
Background="Transparent"
BorderBrush="#BAC8CE"
BorderThickness="1"
CornerRadius="5">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Side, ElementName=uc, Mode=OneWay}"
Value="Up">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:05"
From="Transparent"
To="Green" />
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Green"
To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:05"
From="Transparent"
To="Red" />
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
Duration="00:00:00.5"
From="Red"
To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
hope this helps

Categories

Resources