Toggling visibility using ObjectAnimationUsingKeyFrames - c#

Im not sure why the following is not working. I am attempting hiding and showing a textbox every .2 seconds for 1.2 seconds when the bound model property changes. can anyone see an issue with this style or how i am attempting to do this?
<Style x:Key="FlashStyle" TargetType="TextBlock">
<Style.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated" >
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00.2" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.6" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
<TextBlock Text="{Binding Data.QuotePrice, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource FlashStyle}" />

The Binding.TargetUpdated event does not occur:
Occurs when a value is transferred from the binding source to the binding target, but only for bindings with the NotifyOnTargetUpdated value set to true.
Only thing i can think of besides precedence (which should be fine if this is your actual code).

Related

How to display a blinking overlay at runtime and turn it off again that is controlled by view model properties?

How to display a blinking notification message over parts of the main window of an application, while keeping the controls below of the overlay reachable (clickable) if the overlay is turned off?
The easy part is to create the overlay and build a storyboard for the animation:
<Window.Resources>
<Style x:Key="ds_NotificationStyle" TargetType="DockPanel">
<Setter Property="Opacity" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding EnableNotification}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="ds_BeginCallNotification">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.2" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.4" Duration="0:0:0.4" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="ds_BeginCallNotification" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
Further below in the XAML, the overlay elements (there is a grid populated with other elements and the following DockPanel is placed above of them):
<DockPanel Grid.RowSpan="2" Name="ds_NotificationPanel" Style="{StaticResource ds_NotificationStyle}" Panel.ZIndex="200" Background="AntiqueWhite" Height="100" VerticalAlignment="top">
<Viewbox>
<TextBlock Text="{Binding IncomingCallNotification}" Margin="5" Foreground="Brown" FontWeight="Bold" />
</Viewbox>
</DockPanel>
But there is a problem now with the overlay, blocking all the controls underneath of it.
To solve this, the DockPanel's visibility has to be set to Collapsed. But how to adjust this visibility before and after the animation?
Toggle the visibility at the beginning, using an animation that targets runtime zero of the storyboard:
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
But at the same location, I had no idea how to reset the visibility back to Collapsed.
Using another Storyboard that is run at the ExitActions trigger solved this issue:
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
Here is the complete solution (the DockPanel elements arent' changed):
<Window.Resources>
<Style x:Key="ds_NotificationStyle" TargetType="DockPanel">
<Setter Property="Opacity" Value="0" />
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding EnableNotification}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="ds_BeginCallNotification">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.2" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.4" Duration="0:0:0.4" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="ds_BeginCallNotification" />
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="00:00:00.2" />
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
This may be easy and obvious for many of you, but it took me some times to figure it out. As I would have been grateful for such an answer, I have posted my solution here.

Disable/enable XAML animation

I have next triggers in my XAML:
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsOpened}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Control"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)">
<LinearDoubleKeyFrame KeyTime="0:0:0.30" Value="-310"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="OpenHelpText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="CloseHelpText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ClosePanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="OpenPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Control"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)">
<LinearDoubleKeyFrame KeyTime="0:0:0.30" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="CloseHelpText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="OpenHelpText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ClosePanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="OpenPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.30"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
And I have some dynamic parameter that tells whether the animation be enabled, or not.
(Dynamic - means that animation should be enabled/disabled whenever parameter value changes)
What is the best way to disable/enable animation?
UPD: As an alternative - is that possible to create the same animation in code?
Refer this link like dis....
Bind Element name to main property.Here i used Toggleswitch element name i bind with button
Visibility="{Binding IsOn,ElementName=togglebutton}, Converter={StaticResource BooleanToVisibilityConverter}}" />
Update the trigger criteria on your DataTrigger.
You are embedding the animations in your DataTriggers already.
In your case, perhaps you can leverage MultiDataTriggers to account for multiple conditions that must be met.

MouseDoubleClick routed event doesn't fire up in EventTrigger

My question is fairly simple, because it works in other cases but not with double click mouse event. I want to make editable tab items, and its almost done. Maybe code will clear the situation:
<StackPanel Orientation="Horizontal">
<TextBox x:Name="HeaderEditMode" Text="{Binding Header, Mode=TwoWay}" Visibility="Collapsed" />
<TextBlock x:Name="HeaderDisplayMode" Text="{Binding Header, Mode=TwoWay}" />
<StackPanel.Triggers>
<EventTrigger RoutedEvent="MouseDoubleClick">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderEditMode"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderDisplayMode"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderEditMode"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderDisplayMode"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
If you change MouseDoubleClick to for example to MouseDown or MouseEnter it works perfectly. Any suggestions?
Try wrapping your TextBlock in a ContentControl, and attach the MouseDoubleClick trigger to that instead.

Access a storyboard in window.resources from a template

Given the following style, and a storyboard named animation that lives in <Window.Resources>, how can I pause (and resume) a storyboard triggered from code behind via ((Storyboard)FindResource("animate")).Begin(Tab1, true);
The following code errors saying the PauseStoryboard event can't find animate, which makes sense since it doesn't live in the template. The BeginStoryboard event allows you to bind to resources, but the pause and resume do not.
<Style x:Key="HiddenTabItem" TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type TabItem}">
<Border x:Name="grid">
<ContentPresenter>
<ContentPresenter.Content>
<TextBlock Text="{TemplateBinding Content}"/>
</ContentPresenter.Content>
</ContentPresenter>
</Border>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<PauseStoryboard BeginStoryboardName="animate" />
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
The animate storyboard:
<Window.Resources>
<Storyboard x:Key="animate">
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.2"/>
<DoubleAnimation BeginTime="0:0:2.5" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:0.5"/>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:5.5" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Hidden</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
how can I pause (and resume) a storyboard triggered from code behind
First off save the reference to the storyboard which was kicked off in codebehind in a convenient location. Since you now have that as a reference, subscribe to the mouse enter event from the control which you are targeting. Either in Xaml or most likely in codebehind use that reference to the storyboard to pause it.
Thus removing the need to use a style trigger.

Combination of WPF DataTrigger and EventTrigger isn't working

I have a little question about my code:
<Style TargetType="{x:Type Grid}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status.IsObjectSaving}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty = "Opacity"
From ="1"
To = "0"
BeginTime = "0:0:0"
Duration = "0:0:2" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty = "Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:2"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
When my object would be saved so the grid should be open an show some information. When I start the program for the first time it works, but the second time it doesn't work. So I hope you can help me.
Thanks Daniel
p.s. sorry for my horrible english!
Thanks for answering! I tried to set the values with the following code:
<DataTrigger Binding="{Binding Status.IsObjectSaving}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty = "Opacity"
From = "0"
To = "1"
BeginTime = "0:0:0"
Duration = "0:0:2" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty = "Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:2"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty = "Opacity"
From = "1"
To = "0"
BeginTime = "0:0:2"
Duration = "0:0:2" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty = "Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:2"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
But it's not working. So can you help me to modify the code in a right way?
thanks
Daniel
Animations change values with higher precedence, once the visibility is changed that way the trigger will not be able to modify it. You can replace the setter with an animation (enter and exit actions), that way they have the same precedence.

Categories