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 Framework Element. 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 Framework Element and from the object hierarchy every control somehow inherits from Framework Element 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.
How Style differs from Theme ?
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.
What about Templates ?
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 :
1. ControlTemplate
2. 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 Button 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.
How to define Style?
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 Dependency Property 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.
<TextBox Text="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>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</TextBox.Background>
<TextBox.Foreground>
<SolidColorBrush Color="Black"/>
</TextBox.Foreground>
<TextBox.Effect>
<DropShadowEffect BlurRadius="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>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text" Value="This is a TextBox with Styles"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="CharacterCasing" Value="Lower"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="UltraBlack"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="Black"/>
</Setter.Value>
</Setter>
<Setter Property="Effect" >
<Setter.Value>
<DropShadowEffect BlurRadius="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>
<Style TargetType="{x:Type TextBox}" x:Key="MyTextBoxStyle">
<Setter Property="Text" Value="This is a TextBox with
Styles"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="CharacterCasing" Value="Lower"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="UltraBlack"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="0,20,0,10" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="Black"/>
</Setter.Value>
</Setter>
<Setter Property="Effect" >
<Setter.Value>
<DropShadowEffect BlurRadius="40" Color="Maroon"
Direction="50" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Style="{StaticResource MyTextBoxStyle}" Grid.Row="0" />
<TextBox Style="{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.
<Style TargetType="{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 <TextBox Style="{x:Null}"/> to revert the style.
Members of Style
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.
Using those properties you can define your own styles.
What about Explicit and Implicit Styles ?
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.
Clearly, the above diagram shows the association of Style in Framework Element and from the object hierarchy every control somehow inherits from Framework Element 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.
How Style differs from Theme ?
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.
What about Templates ?
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 :
1. ControlTemplate
2. 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 Button 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.
How to define Style?
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 Dependency Property 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.
<TextBox Text="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>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</TextBox.Background>
<TextBox.Foreground>
<SolidColorBrush Color="Black"/>
</TextBox.Foreground>
<TextBox.Effect>
<DropShadowEffect BlurRadius="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>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text" Value="This is a TextBox with Styles"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="CharacterCasing" Value="Lower"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="UltraBlack"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="Black"/>
</Setter.Value>
</Setter>
<Setter Property="Effect" >
<Setter.Value>
<DropShadowEffect BlurRadius="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>
<Style TargetType="{x:Type TextBox}" x:Key="MyTextBoxStyle">
<Setter Property="Text" Value="This is a TextBox with
Styles"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="CharacterCasing" Value="Lower"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="UltraBlack"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="0,20,0,10" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Color="Cyan" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Red" Offset="1.0"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="Black"/>
</Setter.Value>
</Setter>
<Setter Property="Effect" >
<Setter.Value>
<DropShadowEffect BlurRadius="40" Color="Maroon"
Direction="50" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Style="{StaticResource MyTextBoxStyle}" Grid.Row="0" />
<TextBox Style="{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.
<Style TargetType="{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 <TextBox Style="{x:Null}"/> to revert the style.
Members of Style
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.
Using those properties you can define your own styles.
What about Explicit and Implicit Styles ?
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.




No comments:
Post a Comment