Perhaps the most interesting and most important feature for any WPF application is Styling.
Styling means defining styles for controls, and store in reusable ResourceDictionaries
and hence forth, it could be used later on by calling its name. Styles in WPF could be well compared
with CSS styles. They are both similar in most of the cases, while the former extends the
feature allowing most of the features which WPF have. In this article I will discuss mostly
how you could use Style in your WPF application to enhance the Rich experience
of your UI.

Before we go on further with styles, lets jot down what we
have already discussed so far.

So basically if you have already gone through the articles in the series,
you must have already know most of the things on how you could apply your
styles, how could you define style objects etc. In this article I
will discuss how you could write better styles for your application.

WPF exposes a property Style for every Control. If you look into the
object Hierarchy, the Style is basically a property which exposes an object of Style
in FrameworkElement. So each object can associate it and define custom
setters to manipulate the basic look and feel of a control.

Clearly, the above diagram shows the association of Style in
FrameworkElement and from the object hierarchy every control
somehow inherits from FrameworkElement and hence style will be available to it.
Style is also a WPF object which is inherited form DispatcherObject
which helps in setting different properties of your UI Element.

Before we move further into Styles lets talk about Themes.
Theme is totally different from Styles. Themes are defined at OS level,
or more precisely a Theme can take part of delivering styles all over the Desktop while Styles
are restricted to the contextual area of a WPF window. WPF are capable of retrieving
the color scheme which is defined in OS level. Say for instance, if you do not define style
for your application, the elements in the screen will automatically get styles from external
environment. Say for instance, in XP if you change the theme to something else
you would see that the buttons, TextBox on your WPF window will change its color instantly.
You can even set the Theme which the application would use
programmatically
[^]
from your code.

Every control defines a ControlTemplate. A ControlTemplate defines the overall
structure of the control. As I have already told you, say for instance you have a Button.
Button is a control that is made up of more than one control. It would have a ContentPresenter
which writes the Text over the control, it would have a Rectangle which keeps the boundary of the Button etc. So Template is a special property associated with a Control which specifies how the control will look like structurally. We can
easily define our Template and change the overall structure of a control.

Templates are basically of 2 types :

ControlTemplate

DataTemplate

ControlTemplate defines the structure of the Control.
It means say for instance, you define the ControlTemplate for a
ComboBox. So from ControlTemplate you can easily change the
ToggleButton associated with the ComboBox which opens the
DropDown, you can change the structure of the TextBox, the
Popup etc. So ControlTemplate allows you to change the
overall structure of the Control.

Each control is made up of Data. Say for instance a ItemsControl contains
a number of Data Element which builds the items inside the Popup. The
DataTemplate could be associated with ItemsTemplate and will build up the
Data Block for the ComboBox.

So, you should always remember, ControlTemplate defines the whole Control while the DataTemplate defines each individual Data Element.

Normally a style is an unique object which is used to style WPF controls. Each WPF
element contains a number of Dependency Properties. A dependency property defines the basic
behavior and look of the control in UI. Styles maintains a collection of Setters
which enumerates a DependencyProperty with its value.

Thus you can say a style is a collection of DependencyProperty settings which when applied on a Target will change the behavior of it.

Let us suppose you are going to style a TextBox.

<TextBoxText="This is a TextBox without Styles"HorizontalAlignment="Center"VerticalAlignment="Center"CharacterCasing="Lower"FlowDirection="RightToLeft"FontSize="20"FontWeight="UltraBlack"Width="400"Height="40"><TextBox.Background><LinearGradientBrush><GradientStopColor="Cyan"Offset="0.0"/><GradientStopColor="Yellow"Offset="0.5"/><GradientStopColor="Red"Offset="1.0"/></LinearGradientBrush></TextBox.Background><TextBox.Foreground><SolidColorBrushColor="Black"/></TextBox.Foreground><TextBox.Effect><DropShadowEffectBlurRadius="40"Color="Maroon"Direction="50"Opacity="0.5"/></TextBox.Effect></TextBox>

So I have just designed a TextBox in the above code. The XAML looks straight forward, where I have configured different properties of the TextBox control to create my stylish TextBox. But looking at the code, you might wonder how difficult it would be if you need to redo the same thing again and again for every TextBox you define in your application. This is what the problem is. So WPF comes with an alternative with style. A style is an object that holds this behaviors into a collection of Setters. So lets redefine the same with Styles.

<TextBox><TextBox.Style><StyleTargetType="{x:Type TextBox}"><SetterProperty="Text"Value="This is a TextBox with Styles"/><SetterProperty="HorizontalAlignment"Value="Center"/><SetterProperty="VerticalAlignment"Value="Center"/><SetterProperty="CharacterCasing"Value="Lower"/><SetterProperty="FlowDirection"Value="RightToLeft"/><SetterProperty="FontSize"Value="20"/><SetterProperty="FontWeight"Value="UltraBlack"/><SetterProperty="Width"Value="400"/><SetterProperty="Height"Value="40"/><SetterProperty="Background"><Setter.Value><LinearGradientBrush><GradientStopColor="Cyan"Offset="0.0"/><GradientStopColor="Yellow"Offset="0.5"/><GradientStopColor="Red"Offset="1.0"/></LinearGradientBrush></Setter.Value></Setter><SetterProperty="Foreground"><Setter.Value><SolidColorBrushColor="Black"/></Setter.Value></Setter><SetterProperty="Effect"><Setter.Value><DropShadowEffectBlurRadius="40"Color="Maroon"Direction="50"Opacity="0.5"/></Setter.Value></Setter></Style></TextBox.Style></TextBox>

So you can see, I have defined the Style inside the TextBox and the textbox looks almost the same. The Setters allows you to enumerate all the properties for the TextBox and produced a style inside it whose TargetType is set to {x:Type Button}

Now how this style can be made reusable for many controls ? Yes, this might be your first question that arose in your mind. Yes, if you have read my previous articles, you should already know the use of ResourceDictionaries. So in our case I will shift the style to Resource section for the Window and reuse the code just by calling the Resource key from the Textbox.

<Grid><Grid.Resources><ResourceDictionary><StyleTargetType="{x:Type TextBox}"x:Key="MyTextBoxStyle"><SetterProperty="Text"Value="This is a TextBox with Styles"/><SetterProperty="HorizontalAlignment"Value="Center"/><SetterProperty="VerticalAlignment"Value="Center"/><SetterProperty="CharacterCasing"Value="Lower"/><SetterProperty="FlowDirection"Value="RightToLeft"/><SetterProperty="FontSize"Value="20"/><SetterProperty="FontWeight"Value="UltraBlack"/><SetterProperty="Width"Value="400"/><SetterProperty="Height"Value="40"/><SetterProperty="Margin"Value="0,20,0,10"/><SetterProperty="Background"><Setter.Value><LinearGradientBrush><GradientStopColor="Cyan"Offset="0.0"/><GradientStopColor="Yellow"Offset="0.5"/><GradientStopColor="Red"Offset="1.0"/></LinearGradientBrush></Setter.Value></Setter><SetterProperty="Foreground"><Setter.Value><SolidColorBrushColor="Black"/></Setter.Value></Setter><SetterProperty="Effect"><Setter.Value><DropShadowEffectBlurRadius="40"Color="Maroon"Direction="50"Opacity="0.5"/></Setter.Value></Setter></Style></ResourceDictionary></Grid.Resources><Grid.RowDefinitions><RowDefinitionHeight="Auto"/><RowDefinitionHeight="Auto"/><RowDefinitionHeight="*"/></Grid.RowDefinitions><TextBoxStyle="{StaticResource MyTextBoxStyle}"Grid.Row="0"/><TextBoxStyle="{StaticResource MyTextBoxStyle}"Grid.Row="1"Text="The Style is modified here"FlowDirection="LeftToRight"/></Grid>

So here I have shifted the Style into Resource section and used MyTextBoxStyle key to refer for each TextBox i defined. Notably, the style of both the textboxes remains same, while you can see I have also overridden certain settings in the control itself and it works the same. I have modified the Text of the 2nd TextBox to "The Style is modified here" and also made the FlowDirection to LeftToRight.

Another important thing, that you should always keep into mind, that if you do not define the Key element for the Style in Resource section, it will automatically be applied to all the TextBox you define.

<StyleTargetType="{x:Type TextBox}"></Style>

Say the style you define does not contain any Key. So all the TextBoxes will automatically apply the style when appeared. You can eventually use

The styling of WPF controls is made up with the help of a class called Style. The style object exposes few properties which help you to define various behavior. Lets look into the properties:

Resources : It holds the reference for the ResourceDictionary where the Style is defined.

Setters : It is a collection which holds all the DependencyProperty configuration for the whole control.

TargetType : TargetType defines the type of the control for which the Style can be applied. So based on the TargetType the Style setters are defined to. So if you define a style for TextBox you cannot use Content as property Setter.

BasedOn : This is used to allow Style inheritance. You can use an existing style key to inherit all the properties to a new Style.

Triggers : A collection of Setters which would be applied based on certain conditions.

WPF controls can have two type of styles associated with it. A control can have a style defined in the application and applied to its Style property. If your control is using a Style to define its look and feel or basically your control has set an object of Style into its Style property, then it is using an Explicit Style.

On the other hand, if your control takes the style from external environment (Theme) and the Style property is set to Null, then your control is using Implicit Style. Basically any WPF control automatically defines a DefaultStyle for it, so that you can set only the portion of the control which you need to change.

Say for instance, you have a Button. If you want to have its Text to be colored Red, you just need to change the Foreground of the Button. You need not to define the whole style. If there is no Default Style defined for Buttons, you need to define all the properties individually to make it appear. Thus the default color of the Text is Black if not defined otherwise.

Triggers are a set of styles that work on a particular condition. You can think Trigger as a part of Style which will be set only when the Condition defined for the Trigger is met.

There are few types of Triggers :

Property Trigger : Will be set only when the DependencyProperty of a certain object has been set to a Value.

Data Trigger : Will work for any normal Properties using on Binding.

Event Trigger : Will work only when some event is triggered from the control.

Now to demonstrate let us look into the code below :

<StyleTargetType="{x:Type TextBox}"x:Key="MyTextBoxStyle"><SetterProperty="Text"Value="This is a TextBox with Styles"/><SetterProperty="HorizontalAlignment"Value="Center"/><SetterProperty="VerticalAlignment"Value="Center"/><SetterProperty="CharacterCasing"Value="Lower"/><SetterProperty="FlowDirection"Value="RightToLeft"/><SetterProperty="FontSize"Value="20"/><SetterProperty="FontWeight"Value="UltraBlack"/><SetterProperty="Width"Value="400"/><SetterProperty="Height"Value="40"/><SetterProperty="Margin"Value="0,20,0,10"/><SetterProperty="Background"><Setter.Value><LinearGradientBrush><GradientStopColor="Cyan"Offset="0.0"/><GradientStopColor="Yellow"Offset="0.5"/><GradientStopColor="Red"Offset="1.0"/></LinearGradientBrush></Setter.Value></Setter><SetterProperty="Foreground"><Setter.Value><SolidColorBrushColor="Black"/></Setter.Value></Setter><SetterProperty="Effect"><Setter.Value><DropShadowEffectBlurRadius="40"Color="Maroon"Direction="50"Opacity="0.5"/></Setter.Value></Setter><Style.Triggers><TriggerProperty="IsFocused"Value="True"><SetterProperty="Effect"><Setter.Value><DropShadowEffectBlurRadius="40"Color="Red"Direction="50"Opacity="0.9"/></Setter.Value></Setter></Trigger><MultiTrigger><MultiTrigger.Conditions><ConditionProperty="IsFocused"Value="True"/><ConditionProperty="IsMouseOver"Value="True"/></MultiTrigger.Conditions><SetterProperty="Effect"><Setter.Value><DropShadowEffectBlurRadius="40"Color="Violet"Direction="50"Opacity="0.9"/></Setter.Value></Setter><SetterProperty="Foreground"Value="White"/><SetterProperty="Background"Value="Maroon"/></MultiTrigger></Style.Triggers></Style>

Here you can see I have used Property Trigger to change the DropShadowEffect of TextBox when it is focussed. Every WPF control exposes few properties to work with Property Triggers, which will be set to true based on the control appearance changes. You can use these properties likeIsFocused, IsMouseDown
etc to work around with Property Triggers.

On the second occasion, I have defined a MultiTrigger. MultiTrigger allows you to mention Condition, so that when all the conditions of the MultiTrigger is met, the Property Setters for the object is applied.

So you can see when you hover your mouse over the TextBox and your textbox has its focus in it, only then you see the TextBox to appear in Maroon background and Violet DropShadow effect.

Another interesting thing that you might think very interesting is the support of Animation for WPF. Basically, by the word Animation, we generally think of large Texture graphics in 3D space, which would probably be created in 3DS MAX studio or MAC etc. But believe me there is nothing to worry about this in case of WPF. WPF simplifies the concept Animation to be the change of a property over time.

Say for instance, say you want your textbox to change its color over time, you would write a simple color animation to do this or say you want to change the Opacity of a Border element during time, you need DoubleAnimation to do this. Animation is cool if you are clear about how it works.

I must say, don't make yourself more confused by seeing the types of Animation. Animation is actually categorized in the same way as you categorize variables. Say for instance :

DoubleAnimation : This will animate a Double Value from one value to another. So if you want to change the Width of a TextBox over time you need DoubleAnimation.

ColorAnimation : Same as the above if the type of Changing element is Color, you need ColorAnimation.

SingleAnimation, RectAnimation, PointAnimation, Int32Animaition, ThicknessAnimation etc each of them bears the same meaning.

So basically the basis of Animation types is based on the type of the property for which you want your animation to work on.

Animation can also be categorized into two basic ways :

Animation Without KeyFrames : These are animation that only needs two values, From and To. It gives you a smooth animation based on the Timeline.DesiredFramerate property for the animation.

Animation With KeyFrames : Allows you to specify a KeyFrame collection which lets you define the KeyFrame value on a specified time. So that you can adjust your own animation based on specific time intervals.

Let us take a look at a few examples to make you understand animation feature of WPF:

A StoryBoard can be defined as a Container for TimeLines or a collection of animation timelines for which the object specified in Target will animate. We use StoryBoard to specify Animation within it.

Few important properties of StoryBoard :

RepeatBehaviour : Specifies the number of times for which the StoryBoard repeat the animation.

Target : Specifies the Target for which the storyboard will be applied to.

TargetName : Defines the target and reference it by its name attribute.

TargetProperty : Specifies the property for which the animation will be applied for.

AccelerationRatio / DecelerationRatio : Defines the acceleration or deceleration for the animation.

AutoReverse : Defines whether the StoryBoard will be reversed automatically. This is really cool concept, which allows you to get the reverse of the storyboard timeline automatically generated by the WPF.

Animation can be defined either using KeyFrames or without KeyFrames. KeyFrame allows you to define an intermediate frame so that the animation occurs for each individual frame intervals. There are three types of interpolation for an AnimationwithKeyFrames.

Here the animation is applied as LinearDoubleKeyFrame, which means the animation would be smooth while we define each KeyFrame value based on KeyTime. Here we change the Translation of the Border based on different KeyTime specified such that on 3rd second, the Rectangle will move to 500, at 7th second it will be at 50 and at 13th second it will be at 300. The animation is LinearDouble so the animation is smooth and steady.

SplineAnimation is used to define more realistic animation behavior for your control. It lets you control acceleration and deceleration of the animation. With KeySpline you can define the the cubic bazier curve using Spline Key frame. Lets look at the example

I hope you like my article. I am also happy that I have covered almost most of the topics that you need to know in WPF. There are still a few things left behind, which I would cover in my next article. Please put your valuable feedback for the article.

Share

About the Author

Oh, lets go a bit further to know him better. Visit his Website : www.abhisheksur.com to know more about Abhishek.

Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.http://bit.ly/EXPERTCookBook

Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.

Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well. Have any problem? Write to him in his Forum.