How to animate an IsChecked property?
I have a custom control with a number of ToggleButtons:
<Style TargetType="{x:Type local:ISA88Buttons}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ISA88Buttons}"> <Border x:Name="PART_Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="ISA88States"> ... <VisualState x:Name="AbortingState" Storyboard="{StaticResource sbAbortingState}" /> <VisualState x:Name="AbortedState" Storyboard="{StaticResource sbAbortedState}" /> ... </VisualStateGroup> </VisualStateManager.VisualStateGroups> <StackPanel Margin="1" HorizontalAlignment="Center" Orientation="Horizontal"> ... <ToggleButton x:Name="PART_Button_Abort" Margin="1" IsChecked="False" IsThreeState="True" Tag="Abort"> <ToggleButton.Style> <Style TargetType="{x:Type ToggleButton}"> <Setter Property="OverridesDefaultStyle" Value="True" /> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border x:Name="border" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Background="{StaticResource NormalAbortButtonDrawingBrush}" /> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter TargetName="border" Property="Background" Value="{StaticResource DisabledAbortButtonDrawingBrush}" /> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="{StaticResource MouseOverAbortButtonDrawingBrush}" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsEnabled" Value="True" /> <Condition Property="IsChecked" Value="True" /> </MultiTrigger.Conditions> <MultiTrigger.Setters> <Setter TargetName="border" Property="Background" Value="{StaticResource PressedAbortButtonDrawingBrush}" /> </MultiTrigger.Setters> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsEnabled" Value="True" /> <Condition Property="IsChecked" Value="{x:Null}" /> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard x:Name="sb"> <Storyboard RepeatBehavior="Forever"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="border" Storyboard.TargetProperty="Background"> <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource PressedAbortButtonDrawingBrush}" /> <DiscreteObjectKeyFrame KeyTime="00:00:0.25" Value="{StaticResource NormalAbortButtonDrawingBrush}" /> <DiscreteObjectKeyFrame KeyTime="00:00:0.5" Value="{StaticResource PressedAbortButtonDrawingBrush}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </MultiTrigger.EnterActions> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ToggleButton.Style> </ToggleButton> ... </StackPanel> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> And storyboards:
<Storyboard x:Key="sbAbortingState"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_Button_Abort" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Null}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Key="sbAbortedState"> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_Button_Abort" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteObjectKeyFrame KeyTime="0" Value="True" /> </ObjectAnimationUsingKeyFrames> </Storyboard> When my control is in the “Interrupt” state, the “Interrupt” button blinks, but when I change the state to “Interrupted”, an error occurs:
Unable to animate 'IsChecked' property to 'System.Windows.Controls.Primitives.ToggleButton' using 'System.Windows.Media.Animation.ObjectAnimationUsingKeyFrames'
How can I animate this property using the Storyboard between the three values: true, false and {x:Null} , and not just true and false .
The problem is that you should not set the Boolean value using the ObjectAnimationUsingKeyFrames animation, rather it should be a BooleanAnimationUsingKeyFrames animation with a DiscreteBooleanKeyFrame keyframe.
So your markup will be:
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteBooleanKeyFrame KeyTime="0" Value="{x:Null}" /> </BooleanAnimationUsingKeyFrames> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteBooleanKeyFrame KeyTime="0" Value="True" /> </BooleanAnimationUsingKeyFrames> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteBooleanKeyFrame KeyTime="0" Value="False" /> </BooleanAnimationUsingKeyFrames> I have found a solution. If you want to install bool? property in XAML you should do this:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Null}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <sys:Boolean>True</sys:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Button" Storyboard.TargetProperty="(ToggleButton.IsChecked)"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <sys:Boolean>False</sys:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames>