Introduction
Triggers is used in style to perform action on change any property value or event fires. Triggers create visual effects on controls.
By using Triggers we can change the appearance of Framework Elements.
Background
There are three types of Triggers available.
Event Trigger
Property Trigger
Data Trigger
Using the code
1. Property Trigger
Property Trigger Executes Collections of Setters, when UIElements property value changes.
To create a trigger on any controls, you have to set trigger in style of the control.
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
In the above code, Trigger created on Button. It will set
Opacity
to 0.5 when Buttons
IsPressed
property change. you can set trigger on any Dependency Property of the control. Now you can apply style to Button.
<Button x:Name="PropertyTriggerButton"
Width="160"
Height="40"
Margin="20,0,0,0"
HorizontalAlignment="Left"
Content="IsPressed Property"
Cursor="Hand"
FontWeight="Bold"
Style="{StaticResource ButtonStyle}"
ToolTip="Press To Raise Property Trigger">
When you press the button, the trigger executes.
MultiTrigger
MultiTrigger is used to set action on Multiple Property change. It will execute when all condition are satisfy within
MulitTrigger.Condition
.
<Style x:Key="MulitTriggerButtonStyle" TargetType="Button">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsPressed" Value="True" />
<Condition Property="Background" Value="BlanchedAlmond" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Foreground" Value="Blue" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="BorderBrush" Value="Blue" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
2. Event Trigger
Event Trigger used perform action when
RoutedEvent
of
FrameworkElement
raise.
Event Trigger generally used to perform some animation on control (like : colorAnimation, doubleAnumation using KeyFrame etc.)
Let's first understand Storyboard
and Animation.
An
animation can provide user interface more attractive with look and feel. We can also create visual effects on the control, Animation can be any type like:
change background color of the control
rotate screen in 90 degree angle
move object from one location to another
Change Opacity (FadeIn/FadeOut) of the circle.
Animation is used with Property of the UIElement. WPF provides different types of animation used with properties, like:
ColorAnimation
:
used to animate/change the color property (
SolidColorBrush
,
LinearGradientBrush
) of the UIElement over specific
Duration.
It has two properties
: From(source)
and
To(target)
<Border Name="border1" Width="100" Height="30"
BorderBrush="Black" BorderThickness="1">
<Border.Background>
<SolidColorBrush x:Name="MyBorder" Color="LightBlue" />
</Border.Background>
<Border.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:1"
Storyboard.TargetName="MyBorder"
Storyboard.TargetProperty="Color"
To="Gray" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
ColorAnimationUsingKeyFrames
: also works same as colorAnimation
in Addition to animate object with KeyFrames.
<Border Name="EventTriggerBorder"
Width="100"
Height="30"
BorderBrush="Black"
BorderThickness="1">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFE9DDDA" />
<GradientStop Offset="1" Color="#FF9F6A1D" />
</LinearGradientBrush>
</Border.Background>
<Border.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="EventTriggerBorder"
Storyboard.TargetProperty="Background.GradientStops[0].Color">
<LinearColorKeyFrame KeyTime="0:0:1" Value="#FF00FF" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
This will animate first
GradientStop
color of Border Element from #FFE9DDDA to #FF00FF in 1 seconds with smooth interval. Keytime describes HH:MM:SS values.
DoubleAnimation
used to change values
of width/height of the UIElement on specific Duration.
<Border Name="EventTriggerBorder"
Width="100"
Height="30"
Background="Olive"
BorderBrush="Black"
BorderThickness="1">
<Border.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation AutoReverse="True"
Duration="0:0:2"
From="1"
Storyboard.TargetName="EventTriggerBorder"
Storyboard.TargetProperty="(Border.Opacity)"
To="0.5" />
<DoubleAnimation AutoReverse="True"
Duration="0:0:5"
From="100"
Storyboard.TargetName="EventTriggerBorder"
Storyboard.TargetProperty="(Border.Width)"
To="20" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
In the above snippet, Border width animated from 100 to 20 over duration of 5 seconds. and immediately animated from 20 to 100, because of
AutoReverse
property.
The AutoReverse property will animate object
From
->
To
->
From
.
The same way Border Opacity property changing from 1 to 0.5 and vise a versa.
DoubleAnimationUsingKeyFrames
: Functions same
as DoubleAnimation with addition to KeyFrames Property.
<Border Name="EventTriggerBorder"
Width="100"
Height="30"
Background="Olive"
BorderBrush="Black"
BorderThickness="1">
<Border.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="EventTriggerBorder"
Storyboard.TargetProperty="(FrameworkElement.Width)">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="250" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="EventTriggerBorder"
Storyboard.TargetProperty="(FrameworkElement.Width)">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="100" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
Storyboard is used to provide animation to the properties of the UIElement. Storyboard has
TargetName
and
TargetProperty
attached
properties for apply animation to the Control (
TargetName
) and Control Property (
TargetProperty
).
<Storyboard x:Key="LoadStoryBoard"
AutoReverse="True"
RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LoadedBorder"
Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
In the above snippet, Opacity of the border will change from 1 to 0.4 wihtin 0.7 seconds.
RepeatBehavior
Property ia used to Repeat Animation based on value of the
property. To start a Storyboard, you have to call action BeginStoryboard within EventTrigger of the Control. EventTrigger describes perform action when any event executes by the control. like:
<Border.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
</EventTrigger>
</Border.Triggers>
3. DataTrigger
As the name suggest, DataTrigger applies property value to perform action on Data that Binding to the UIElement. DataTrigger allows to set property value when Binding Data matches specified condition. For
example:
<DataTemplate>
<Grid Margin="0 5 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image x:Name="viewImage"
Grid.Row="0" Width="100"
Height="60" HorizontalAlignment="Center"
Source="{Binding Picture}" Stretch="Fill" />
<TextBlock x:Name="viewText"
Grid.Row="1" Margin="0 5 0 0"
HorizontalAlignment="Center"
FontWeight="Black" Foreground="Green"
Text="{Binding Title}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Picture}" Value="{x:Null}">
<Setter TargetName="viewImage" Property="Source" Value="/Images/noImage.png" />
<Setter TargetName="viewText" Property="Text" Value="No Image Available" />
<Setter TargetName="viewText" Property="Foreground" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
In above example,
DataTrigger
created on
Picture
property of Binding data. Setters object of the DataTrigger describes property values to apply when
Binding Data match the condition. Picture is
Byte[]
property of the class. If Picture is null then DataTrigger applies on Image to set Image Source to NoImage, otherwise it will set Image Source from Picture.
Same as if Picture is null, applies
TextBlock
value to
"No Image Availalbe"
and
Foreground
color to
Red
otherwise sets Default value from Data.
4. MultiDataTrigger
MultiDataTrigger is same as DataTrigger in addition property value applied on multiple condition is matches.
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Picture}" Value="{x:Null}" />
<Condition Binding="{Binding Path=Title}" Value="Waterfall" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter TargetName="viewImage" Property="Source" Value="/Images/noImage.png"/>
<Setter TargetName="viewImage" Property="Opacity" Value="0.5" />
<Setter TargetName="viewText" Property="Background" Value="Brown" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</DataTemplate.Triggers>
In above code, all collections of setter applies property value when below two conditions
are satisfied:
Picture = null
Title = 'Waterfall'
Otherwise the default property values are applied.
Having 9+ years of experience in Microsoft.Net Technology.
Experience in developing applications on Microsoft .NET Platform ( Asp.Net, WPF, Silverlight, Windows Phone 7/8).
Experience and knowledge of software design methodologies (Agile), object oriented design, and software design patterns (MVVM).
Experience in Developing android mobile application using Xamarin (mono for android) framework.
http://hirenkhirsaria.blogspot.com/
I have a huge problem, in our application we have a style trigger on a menuitem, IsHighlighted true and false. But sometimes business rules will force another menuitem to be the selected one.
In this situation i want to force the selected menuitem to be the highlighted one, is this possible???
Best Regards
Martin Jonsson
please try with below steps.
1. first add TabControl in your page and create Storyboard resource for TabItems.
RepeatBehavior
="
Forever"
Storyboard.TargetName
="
FirstTab"
Storyboard.TargetProperty
="
(TabItem.Background).(SolidColorBrush.Color)"
>
<
ColorAnimation
Duration
="
0:0:1"
From
="
GreenYellow"
To
="
Magenta"
/
>
<
/Storyboard
>
<
Storyboard
x:Key
="
SecondTabStoryboard"
BeginTime
="
00:00:00"
RepeatBehavior
="
Forever"
Storyboard.TargetName
="
SecondTab"
Storyboard.TargetProperty
="
(TabItem.Background).(SolidColorBrush.Color)"
>
<
ColorAnimation
Duration
="
0:0:1"
From
="
GreenYellow"
To
="
Magenta"
/
>
<
/Storyboard
>
<
/Window.Resources
>
<
TabControl
x:Name
="
mainTabControl"
SelectionChanged
="
mainTabControl_SelectionChanged"
>
<
TabItem
x:Name
="
FirstTab"
Header
="
First Tab"
IsSelected
="
True"
/
>
<
TabItem
x:Name
="
SecondTab"
Header
="
Second Tab"
IsSelected
="
True"
/
>
<
/TabControl
>
<
/Grid
>
2. after that write code for highlight items in TabControl SelectionChanged event.
private
void
mainTabControl_SelectionChanged(
object
sender, SelectionChangedEventArgs e)
Storyboard firstStoryboard =
new
Storyboard();
firstStoryboard = (Storyboard)TryFindResource(
"
FirstTabStoryboard"
);
Storyboard secondStoryboard =
new
Storyboard();
secondStoryboard = (Storyboard)TryFindResource(
"
SecondTabStoryboard"
);
TabControl tabControl = sender
as
TabControl;
TabItem selectedTabItem = tabControl.SelectedItem
as
TabItem;
if
(selectedTabItem !=
null
)
if
(selectedTabItem.Name ==
"
FirstTab"
)
firstStoryboard.Begin(selectedTabItem,
true
);
secondStoryboard.Begin(selectedTabItem,
true
);
to stop highlighting items you can call Stop method of storyboard (firstStoryboard.Stop()).
you can implement this way in your application.
Thanks,
Hiren
No, there is not any condition like NOT NULL or not empty is not available.
you can do it by using converters also.
Thanks,
Hiren
Can I skip the event trigger to call storyboard.Bigin() ?
Member 7897515
24-Nov-13 16:54
Member 7897515
24-Nov-13 16:54
I have a process indicator using WPF animation, I want control the storyboard.Bigin() Can I skip the event trigger? or can I define a property in style say, IsPressed, then trigger BiginStoryboard ? there are many buttons need to trigger this animation.
Thanks in advance.
Peter Chen
Re: Can I skip the event trigger to call storyboard.Bigin() ?
Hiren Khirsaria
25-Nov-13 6:28
Hiren Khirsaria
25-Nov-13 6:28
yes, you can remove event trigger.
there is one alternate to start storyboard on IsPressed,
you can start storyboard from code behind on button click, like
first you can create storyboard within resources :
<Window.Resources>
<Storyboard x:Key=
"
MouseHoverStoryBoard"
>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=
"
MyButton"
Storyboard.TargetProperty=
"
(FrameworkElement.Width)"
>
<EasingDoubleKeyFrame KeyTime=
"
0:0:0.1"
Value=
"
250"
/>
</
DoubleAnimationUsingKeyFrames
>
<ColorAnimationUsingKeyFrames Storyboard.TargetName=
"
MyButton"
Storyboard.TargetProperty=
"
Background.GradientStops[0].Color"
>
<LinearColorKeyFrame KeyTime=
"
0:0:1"
Value=
"
#FF00FF"
/>
</
ColorAnimationUsingKeyFrames
>
</
Storyboard
>
</
Window.Resources
>
this is your button :
FontWeight=
"
Bold"
>
<Button.Background>
<LinearGradientBrush StartPoint=
"
0,0"
EndPoint=
"
0,1"
>
<GradientStop Offset=
"
0"
Color=
"
#FFE4D0D0"
/>
<GradientStop Offset=
"
1"
Color=
"
#FF663434"
/>
<GradientStop Offset=
"
0.513"
Color=
"
#FFA48181"
/>
</
LinearGradientBrush
>
</
Button.Background
>
</
Button
>
on button click, you can find storyboard from you resources and start it
private
void
MyButton_Click(
object
sender, RoutedEventArgs e)
Storyboard sb =
this
.Resources[
"
MouseHoverStoryBoard"
]
as
Storyboard;
sb.Begin();
Button Event trigger click event should change the textbox value any idea
keerth516
6-Nov-13 21:12
keerth516
6-Nov-13 21:12
i have a popup control which contains calendar and two buttons.On togglebutton click it will popup.I am applying this style to a textbox.
Now am able to bind the calendar selected value to the text box.How can i achieve the below scenario.On button click event want to bind the todaydate to textbox?
<
Button
Content
="
Today"
Grid.Row
="
1"
Width
="
50"
VerticalAlignment
="
Center"
Margin
="
20 0 0 10"
Name
="
btnToday"
>
<
/Button
>
any idea to achieve this?
In this class MainWindowViewModel what's use of string commonPath = "pack://application:,,/Images"; ??
I mean we can't access directly image folder ?
Web04
2.8:2023-10-29:1