I have a label with an image inside. I'd like to apply a simple animation: changing the opacity property for achieving a fade-in effect after the label is loaded (or when is visible or whatever)
But this doesn't work:
<Label ContentTemplate="{DynamicResource ImageLabelDataTemplate}" Canvas.Left="36" Canvas.Top="394" Height="116" Name="PreviousVirtualButton" Width="100" Visibility="Hidden">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
I'd like to see how the label is fading in on the screen.
Thanks in advance.
Try this:
<Window x:Class="WpfApplicationUnleashed.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Width="200" MinWidth="200" MaxWidth="300" MaxHeight="120" MinHeight="120" Height="120">
<Grid>
<Label Canvas.Left="36" Content="HELLO" Canvas.Top="394" Height="116" Name="PreviousVirtualButton" Width="100">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<EventTrigger RoutedEvent="Label.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
</Window>
If you remove the Visibility="Hidden", it will work (assuming you want it to fade in when it loads). Otherwise, set the Visibility to Visibility.Visible from code-behind when you want it to start fade in. Also, make sure that in the ContentTemplate you have something visible.
Are you setting the label visible in your code somewhere? You have to set it to be visible in order for the animation to trigger.
C# example:
previousVirtualButton.Visibility = System.Windows.Visibility.Visible;
Related
I'm making a "traffic light" animation controlled by radiobuttons in xaml. I'm using an ellipse style to change the color and animate the movement. The problem is, the animation only works when the ellipse is moving down (to a higher value of Canvas.Top), but doesn't work when it's moving up (to a lower value of Canvas.Top).
Here is the code:
<Window x:Class="hw05.MainWindow"
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:local="clr-namespace:hw05"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="Red"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=RedRB}" Value="True">
<Setter Property="Fill" Value="Red"></Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:0.400" To="83">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=YellowRB}" Value="True">
<Setter Property="Fill" Value="Orange"></Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:0.400" To="133">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=GreenRB}" Value="True">
<Setter Property="Fill" Value="Green"></Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:0.400" To="183">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Canvas>
<RadioButton Name="RedRB" GroupName="One" IsChecked="True" Canvas.Left="50" Canvas.Top="100">first</RadioButton>
<RadioButton Name="YellowRB" GroupName="One" IsChecked="False" Canvas.Left="50" Canvas.Top="150">second</RadioButton>
<RadioButton Name="GreenRB" GroupName="One" IsChecked="False" Canvas.Left="50" Canvas.Top="200">third</RadioButton>
<Ellipse Name="Light" Width="50" Height="50" Canvas.Left="180" Canvas.Top="83"></Ellipse>
</Canvas>
</Window>
You should know that triggers like Triggerand DataTrigger are state based: you have an enter action to reflect the transition to the state (e.g., IsChecked: false => true) and an exit action to reflect the transition from the state (e.g., IsChecked: true => false). You are currently only defining an animation for the entering transition. So from the animation's perspective the entering state is never left. DataTrigger.EnterAction will hold the animation state until DataTrigger.ExitAction was executed => state based.
In your scenario it makes more sense to trigger the animation event based: the animation is executed when a certain event occurred (e.g., RadioButton.Checked) and on hold until the next event occurred. Each animation animates the values of the previous animation (if FillBehavior="Hold", which is the default).
The following example has moved the animation to the Canvas as this defines a common name scope of all participating elements:
<Canvas>
<RadioButton Name="RedRB" GroupName="One" IsChecked="True" Canvas.Left="50" Canvas.Top="100">first</RadioButton>
<RadioButton Name="YellowRB" GroupName="One" IsChecked="False" Canvas.Left="50" Canvas.Top="150">second</RadioButton>
<RadioButton Name="GreenRB" GroupName="One" IsChecked="False" Canvas.Left="50" Canvas.Top="200">third</RadioButton>
<Ellipse Name="Light"
Fill="Red"
Width="50" Height="50"
Canvas.Left="180" Canvas.Top="83" />
<Canvas.Triggers>
<EventTrigger RoutedEvent="RadioButton.Checked" SourceName="RedRB">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="Light"
Duration="0:0:0.400" To="83" />
<ColorAnimation Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)"
Storyboard.TargetName="Light"
To="Red" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="RadioButton.Checked" SourceName="YellowRB">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="Light"
Duration="0:0:0.400" To="133" />
<ColorAnimation Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)"
Storyboard.TargetName="Light"
To="Yellow" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="RadioButton.Checked" SourceName="GreenRB">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="Light"
Duration="0:0:0.400" To="183" />
<ColorAnimation Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)"
Storyboard.TargetName="Light"
To="Green" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
I am trying to create a designer like Visual Studio.
Suppose I have a Grid.
Inside that I have a TextBox and a TextBlock. For better understanding look at the sample code below:
<Page.Resources>
<Style x:Key="myStyle" TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="DodgerBlue" />
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Border Style="myStyle">
<Grid>
<Border Style="myStyle">
<TextBox ...... />
</Border>
<Border Style="myStyle">
<TextBlock ...... />
</Border>
</Grid>
</Border>
Now when I mouseOver on any of the element I want to get a border around it.
My Problems:
I get a border around grid as well as a border around textblock when mouse cursor is over textblock.
When my mouse cursor goes over empty area of grid the border is not shown.
Requirements :
when mouse cursor goes over textblock, the border around grid should become invisible.
when mouse cursor goes over empty area in grid, the border around grid should become visible.
Please suggest the changes that I should make in the above code to have the required functionality.
Why did you assign myStyle to the outter Border? Just leave that out.
1: I think, your idea with glowing parent border is not good. Because it will be blink whenever user hold mouse over the grid. Perhaps, it will annoy user :)
2: Try to set Grid.Background="Transparent".
Try this
<Grid Background="LightGray" >
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Grid_Bd" Duration="0:0:0.1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Grid_Bd" Duration="0:0:0.1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid Height="50" Width="50">
<Border x:Name="TextBlock_Bd" Opacity="0" BorderBrush="Blue" BorderThickness="1"/>
<TextBlock Text="Hello !!" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TextBlock_Bd" Duration="0:0:0.1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TextBlock_Bd" Duration="0:0:0.1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Grid>
<Border x:Name="Grid_Bd" Opacity="0" BorderBrush="Red" BorderThickness="1"/>
</Grid>
Is there any way to write a Style for a control that changes width of another control?
<Style x:Key="SubMenuStyle" TargetType="Label">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="LightCyan"/>
<Style.Triggers>
<EventTrigger RoutedEvent="MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Menu" Storyboard.TargetProperty="Width" To="0" Duration="0:0:.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
This code leads to error:
TargetName property cannot be set on a Style Setter
I know I can write codes below and it works:
<Label Name="Owners" Margin="0,1,0,0" MouseLeftButtonDown="SubMenuClicked" Style="{StaticResource SubMenuStyle}">
<Label.Triggers>
<EventTrigger RoutedEvent="MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Menu" Storyboard.TargetProperty="Width" To="0" Duration="0:0:.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Label.Triggers>
</Label>
But since I use this trigger in multiple labels I want to write it in a style once.
This is my code to define controls:
<Border Name="Menu" Grid.Column="2" Grid.Row="1" Width="0" HorizontalAlignment="Right" BorderBrush="LightBlue" BorderThickness="2" CornerRadius="2" Background="LightCyan">
<StackPanel Name="MenuPanel">
<Button Style="{StaticResource MenuButtonsStyle}">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ListsMenu" Storyboard.TargetProperty="Height" To="86" Duration="0:0:.6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<StackPanel Name="ListsMenu" Height="0">
<Label Name="Owners" Margin="0,1,0,0" MouseLeftButtonDown="SubMenuClicked" Style="{StaticResource SubMenuStyle}"/>
<Label Name="Contacts" MouseLeftButtonDown="SubMenuClicked" Style="{StaticResource SubMenuStyle}"/>
<Label Name="Groups" MouseLeftButtonDown="SubMenuClicked" Style="{StaticResource SubMenuStyle}"/>
</StackPanel>
</StackPanel>
</Border>
Scenario: There is a border, It's default width is zero, It will raise to 165 in another trigger which works fine, I want to animate it to zero again when labels are clicked, but I can not access the width of that border in lables style
You claim that you use triggers in multiple labels so you can define trigger one time like this
<Storyboard x:Key="animation">
<DoubleAnimation Storyboard.TargetName="ListsMenu" Storyboard.TargetProperty="Height" To="86" Duration="0:0:.6"/>
</Storyboard>
and later when you need you can call it
<EventTrigger RoutedEvent="MouseEnter" >
<BeginStoryboard Storyboard="{StaticResource animation}"/>
</EventTrigger>
But I'm a bit confused what you meant to acquire.
You cannot get access in style since style does not have a namescope, as it was said. If it changes label's width you could do this in style like this
<Style x:Key="style_button" TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" To="300" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
but it invokes by StoryBoard.TargetName to another object.
try :
<EventTrigger RoutedEvent="MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.Target="{Binding ElementName=Menu}"
Storyboard.TargetProperty="Width" To="0" Duration="0:0:.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
TargetName is only valid inside Templates.
I have the following XAML code which triggers an animation of the rectangle when the LastDataUpdate field is changed. LastDataUpdate is a DateTime within a class that implements INotifyPropertyChanged. I'd like the animation to NOT run if the LastDataUpdate==DateTime.MinValue. Is there any way I can implement this in the XAML?
<Rectangle x:Name="NewDataAnimation" Tag="{Binding Path=LastDataUpdate, NotifyOnTargetUpdated=True}" Opacity="0" Width="5" Height="5" Fill="LawnGreen" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle.Style>
<Style>
<Style.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:0" To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:4" From="1.0" To="0.0" BeginTime="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
Andrew
Why, not trigger on the property itself and have a converter determine whether to execute animation?
Below XAML assumes that you create a converter which will evaluate the LastDataUpdate against the value that you don't want. If you set LastDataUpdate to DateTime.MinValue, the animation won't start. As soon as you make a change, the binding will be forced to re-evaluate through PropertyChanged, and will let converter do its decision-making...
<Rectangle Opacity="0" Width="5" Height="5" Fill="LawnGreen" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle.Style>
<Style>
<Style.Triggers>
<Trigger Property="{Binding LastDataUpdate, Converter={StaticResource LastDataUpdateToDoAnimation}}" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:0" To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:4" From="1.0" To="0.0" BeginTime="0:0:2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
How to Begin a StoryBoard when IsOpen property of a Popup is set to True?
ex:
<EventTrigger RoutedEvent="{Binding IsOpen, ElementName=pop}">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="pop"
Storyboard.TargetProperty="Height"
Duration="0:0:1"
From="0.0"
To="200" />
<DoubleAnimation Storyboard.TargetName="pop"
Storyboard.TargetProperty="Width"
Duration="0:0:1"
From="0.0"
To="{Binding ElementName=root,Path=ActualWidth}" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
I know EventTrigger RoutedEvent="{Binding IsOpen, ElementName=pop} is not ok
Thank you!
Since you did not mark for Answer, I assumed you still need some help in this.
Here is a code snippet that will work your way (as per H.B.'s post)
<Window x:Class="WpfTestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="PopupStyle" TargetType="{x:Type Popup}">
<Style.Triggers>
<Trigger Property="IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Height"
Duration="0:0:1"
From="0.0"
To="200" />
<DoubleAnimation
Storyboard.TargetProperty="Width"
Duration="0:0:1"
From="0.0"
To="500" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Content="Button" Height="29" HorizontalAlignment="Left" Margin="24,19,0,0" Name="button1" VerticalAlignment="Top" Width="90" Click="button1_Click" />
<Popup Name="pop" Style="{StaticResource PopupStyle}" >
<Grid Background="Red">
<TextBlock Text="I am in pop up" />
</Grid>
</Popup>
</Grid>
and the button click event handler in code behind to open the pop up..
private void button1_Click(object sender, RoutedEventArgs e)
{
pop.PlacementTarget = (Button)sender;
pop.IsOpen = true;
}
Create a Style for the Popup.
Trigger on IsOpen -> true
Use Trigger.EnterActions to start a storyboard.