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.
Related
I would like to create simple animation which type is based on some value. I need to change color of text in TextBlock control, but the target color is depending on bounded variable. I've already created 2 DataTriggers and depending on a value of my bounded variable, a proper animation should start. At the beginning everything seems to work properly (AnimationValue is equal to 0 on start), when the value changes to 1, animation runs, then value returns to 0. The problem is, when the value turns to 2 (Animation with another color also runs) and then again 0, the first animation is not going to run anymore but the second one still works in a proper way.
<Border
Grid.Column="0"
Background="Transparent">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="32"
Foreground="White"
Text="MyText">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AnimationValue}" Value="1">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="Gray"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="White"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=AnimationValue}" Value="2">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="Firebrick"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="White"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
There is no problem with setting a correct value - i've checked it using a debugger and everytime correct value is set. 0 is always between 1 and 2. DataContext is also not a problem - a connection between View and ViewModel is not being broken. I've noticed that broken animation is always the first one in xaml file. Now the "Gray" animation stops working correctly, but if i change order in xaml file, firebrick animation will be the broken one. Thanks for any help.
It looks like running StoryBoards in triggers is a weird thing. I don't have a technical explanation as to how they behave but here is a SO question where I found an answer for you.
Here is some code based on the answer above that works:
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AnimationValue}" Value="0">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Animation1" />
<StopStoryboard BeginStoryboardName="Animation2" />
<BeginStoryboard x:Name="Animation0">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="White"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=AnimationValue}" Value="1">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Animation0" />
<StopStoryboard BeginStoryboardName="Animation2" />
<BeginStoryboard x:Name="Animation1">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="Gray"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=AnimationValue}" Value="2">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Animation0" />
<StopStoryboard BeginStoryboardName="Animation1" />
<BeginStoryboard x:Name="Animation2">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Foreground.Color"
To="Firebrick"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
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.
I want to change the background color to red instantly if a property is true. Then revert slowly back to default background color.
My first attempt, problem: Default color appears instantly and not reverting slowly over time
<DataTrigger Binding="{Binding HasValueChanged}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding HasValueChanged}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.(SolidColorBrush.Color)" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
My second attempt, problem: Color reverses like it should, but never goes red again if the property remains true
<DataTrigger Binding="{Binding HasValueChanged}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Red" AutoReverse="True" Storyboard.TargetProperty="Background.(SolidColorBrush.Color)" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
As long as you don't set a Timeline's FillBehavior to Stop, it keeps holding the final property value until it is replaced by another Timeline.
So this works:
<DataTrigger Binding="{Binding HasValueChanged}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color"
To="Red" Duration="0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color"
From="Red" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
I'm getting this exception , i'm trying to change the texenter code heretbox width when the mouse on over the textbox
this is thh exception :
Cannot animate the 'Width' property on a
'System.Windows.Controls.TextBox' using a
'System.Windows.Media.Animation.DoubleAnimation'. For details see the
inner exception.
<Style TargetType="TextBox">
<Setter Property="BorderBrush" Value="#248FB3" />
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="AcceptsReturn" Value="True"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width" To="250" >
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width" To="250"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
You have to set either Width on your TextBox element or, From property on DoubleAnimation. When you don't set either, it gets default value of the Width property which is Double.NaN, so it doesn't know from where to start.
The default "Grid" is displayed.
In step one and "Hide_MouseUp", animation works.
And then in no way responds to IsEnabled.
Please Please help me to solve this problem.
I am waiting for your warm response :)
style:
<Style x:Key="ShowHideVisibilityStyle" TargetType="{x:Type Grid}">
<Setter Property="Opacity" Value="1"></Setter>
<Setter Property="Margin" Value="0,50,0,0"></Setter>
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:0.5" />
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
From="-600,50,0,0"
To="0,50,0,0"
Duration="0:0:0.1"
/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:0.5" />
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
BeginTime="0:0:0.5"
To="-600,50,0,0"
Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
XAML:
<Grid x:Name="SettingPage" Width="290" Style="{DynamicResource ShowHideVisibilityStyle}">
<!-- code -->
</Grid>
Code Test For Change status IsEnabled to {False or True}
private void Hide_MouseUp(object sender, MouseButtonEventArgs e){
SettingPage.IsEnabled = false;
}
private void Show_MouseUp(object sender, MouseButtonEventArgs e){
SettingPage.IsEnabled = true;
}
Hi, I find the solution :)
for using two triggers on one property "Trigger.EnterActions" and "Trigger.ExitActions" should be used instead of using two separate Triggers
excuse me for my bad english :D
Code:
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- Animation -->
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<!-- Animation -->
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
It's a simple fix. Just move the "Enabling" Animation into an ExitTrigger:
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:0.5" />
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
BeginTime="0:0:0.5"
To="-600,50,0,0"
Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:0.5" />
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
From="-600,50,0,0"
To="0,50,0,0"
Duration="0:0:0.1"
/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>