Sunday, December 18, 2016

Style Examples - First

Case 1 : Consider a case where we have a Button in user control and we want following things

Backgrond  : Green
FontStyle  : Italic
Margin : 5
    <UserControl.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Green"></Setter>
            <Setter Property="FontStyle" Value="Italic"></Setter>
            <Setter Property="Margin" Value="5"></Setter>           
        </Style>

    </UserControl.Resources>

        <StackPanel Orientation="Horizontal">
            <Button Content="It" Width="100" Height="30"></Button>
            <Button Content="is" Width="100" Height="30"></Button>
            <Button Content="my style" Width="100" Height="30"></Button>
        </StackPanel>

Sunday, December 11, 2016

Scope of styles

Scope of styles

In the previous post (Introduction of Style) , we introduce the concept of styles, in which we used a very basic example of locally define style, which targeted a TextBlock.
Style can defined in several different scopes, it depends where and how you want to use them.

In this post,we will see in how many different ways styles can be defined.

Local control specific style

You can actually define a style directly on a control. in this scope, style can be used in control itself only.

<Window x:Class="WpfTricks.LocalStyle"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LocalStyle" Height="300" Width="300">
    <Grid>
        <TextBlock Width="200" Height="50" Text="Local Style">
            <TextBlock.Style>
                <Style>
                    <Setter Property="TextBlock.Foreground" Value="Red" />
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>



<Window x:Class="WpfTricks.LocalStyle"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LocalStyle" Height="300" Width="300">
    <Grid>
        <TextBlock Width="200" Height="50" Text="Local Style">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Setter Property="Foreground" Value="Red" />
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>
  


Local child control style

When style is define in the Resource of a control , you can target the child control of this control.

<Window x:Class="WpfTricks.LocalChildControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Local Child Control Style" Height="150" Width="300">
    <Grid>
        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="Label">
                    <Setter Property="Background" Value="Yellow"></Setter>
                    <Setter Property="Foreground" Value="Red"></Setter>
                    <Setter Property="Margin" Value="5,5"></Setter>
                </Style>
            </StackPanel.Resources>
            <Label>Label 1</Label>
            <Label>Label 2</Label>
            <Label>Label 3</Label>
        </StackPanel>
    </Grid>
</Window>


Window Level Style

In this scope of style, specific style can be use with in the Window/UserControl for all controls for which style is targeted, In this scope we have to define style under the Window/UserControl resource

<Window x:Class="WpfTricks.WindowLevelStyle"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window Level Style" Height="150" Width="300">
    <Window.Resources>
        <Style TargetType="Label">
            <Setter Property="Background" Value="Yellow"></Setter>
            <Setter Property="Foreground" Value="Red"></Setter>
            <Setter Property="Margin" Value="5,5"></Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Label>Label 1</Label>
            <Label>Label 2</Label>
            <Label>Label 3</Label>
        </StackPanel>
    </Grid>
</Window>


Application Level Styles

If we want to define global styles for whole application(use application wide) so that it can be use across different windows/user controls , we need to create style in App.xaml file similar to above way, like this we can use these styles application wide.



<Application x:Class="WpfTricks.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="WindowLevelStyle.xaml">
    <Application.Resources>
        <Style TargetType="Label">
            <Setter Property="Background" Value="Yellow"></Setter>
            <Setter Property="Foreground" Value="Red"></Setter>
            <Setter Property="Margin" Value="5,5"></Setter>
        </Style>
    </Application.Resources>
</Application>



<Window x:Class="WpfTricks.ApplicationLevelStyle"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ApplicationLevelStyle" Height="200" Width="300">
    <Grid>
        <StackPanel>
            <Label>Label 1</Label>
            <Label>Label 2</Label>
            <Label>Label 3</Label>
        </StackPanel>
    </Grid>
</Window>



Introduction of Styles


In ley man language wpf style work like HTML CSS, we set properties in style for a control, which make it possible to reuse it in the application. So Style is a way to set some property values to one or more controls.


Take an example to understand this concept.


Suppose we want an application where all TextBlock's background should be Gray, FontStyle Italic and Background Yellow then there are two ways

1. Set the Background and FontStyle property for every TextBlock in application.        <StackPanel Orientation="Horizontal">
            <TextBlock Foreground="Gray" Background="Yellow" FontStyle="Italic" Text="My" Height="25" Margin="5" Padding="5"></TextBlock>
            <TextBlock Foreground="Gray" Background="Yellow" FontStyle="Italic" Text="First" Height="25" Margin="5" Padding="5"></TextBlock>
            <TextBlock Foreground="Gray" Background="Yellow" FontStyle="Italic" Text="Style" Height="25" Margin="5" Padding="5"></TextBlock>
        </StackPanel>
This is not maintainable and scalable so to get rid of this we have a solution says create a style.

       <Window x:Class="WpfTricks.Introduction"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Introduction" Height="150" Width="350">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Gray"></Setter>
            <Setter Property="FontStyle" Value="Italic"></Setter>
            <Setter Property="Background" Value="Yellow"></Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="My" Height="25" Margin="5" Padding="5"></TextBlock>
            <TextBlock Text="First" Height="25" Margin="5" Padding="5"></TextBlock>
            <TextBlock Text="Style" Height="25" Margin="5" Padding="5"></TextBlock>
        </StackPanel>
    </Grid>
</Window>


There are some elements to define styles
Setters: Sets the property values
Triggers: Change the style settings
BasedOn: Creates a specialised style that inherits the settings of another style
TargetType: Gets or Sets the Control for which the style is intended   

Setters

Setter is use to set the property of a style 
e.g.
        <Style TargetType="TextBox">
            <Setter Property="Foreground" Value="Red"/>
        </Style> 
     
BasedOn

BasedOn is use to inherit the current style and define a new style, the default value of BaseOn is null when we are not using it. it is a very useful way to extend the style. when current style need to unchanged.
example 1:
we have a style in App.xaml for TextBox for foreground red
       <Style TargetType="TextBox">
            <Setter Property="Foreground" Value="Red"/>
        </Style>
Text in Textboxes will display with red color, now we need textbox in some windows should have fontsize 14 , then instead of creating complete new style, we can inherit new one and set the fontsize.      
        <Style TargetType="TextBox" x:Key="style2" BasedOn="{StaticResource {x:Type TextBox}}" >
            <Setter Property="FontSize" Value="20"/>
        </Style>
[
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
]
example 2 : When Key is defined
       <Style TargetType="TextBox" x:Key="style1">
            <Setter Property="Foreground" Value="Red"/>
        </Style>

     <Style TargetType="TextBox" x:Key="style2" BasedOn="{StaticResource style1}">
            <Setter Property="FontSize" Value="20"/>
      </Style>
in example 1 we are using x:Key.
if we are using only Target type and not define the key in the style then style will apply to all target Controls( we will understand about key in next paras)x:Key: Define key name to use style in requred element.

How to use x:Key
<TextBlock style="{StaticResource [style key]}"/>
<TextBlock style="{StaticResource style2}"/>

[
<Style x:Key="commonStyle" TargetType="{x:Type FrameworkElement}">
    <!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource commonStyle}" />
]


Target Type
In defining style, it need to tell what is its target element, in above code will show error that it is not recognizable property
<Style TargetType="TextBlock">
  <Setter Property="HorizontalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
  <Setter Property="FontSize" Value="14"/>
</Style>



TargetType :
Gets or sets the type for which this style is intended(planned).


        <Style TargetType="TextBox">
            <Setter Property="Foreground" Value="Red"/>

        </Style>

<Style TargetType="{x:Type [element name]}">
    <!-- Setters -->
</Style>

It insure the type safety.
The style should target a specific type in order to know what properties to set.

Note: However, there is a work around. You can take the common properties of all the types you have and define them in one style. Then make specific styles for each of the specific controls and use the BasedOn property to inherit from the basic style.

Triggers:
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.
i am not explain trigger here, you will read in next post , to read click here.
For every property we need to define one setter in style
We need to write the name of the property and its value.

Understanding Resource Dictionary

Style are define in the resource dictionary.
each style has a unique identifier and target type.
to assign a style in an element a unique key is use with the help of StaticResource markup extension

Advantage: The advantage of creating style is to re-use the style anywhere in its scope, and when ever we need to change in the style , we can change it easily and it will reflect everywhere.
We are now understand how to use style

Scope of style
The Scope of style limits to in which level it is define
Style can be define in following levels.
  • Application Level
  • Window Level
  • Control Level
  • Layout Level
We will read about scope and how to define in different scope in next posts.
Most Basic Example
Example 1:  In the application all text box need with Yellow Background.

In this case we have to create the style for element TextBox, Set property is Background,
    
   <Window x:Class="WpfTricks.BasicStyle"
        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 TargetType="TextBox">
            <Setter Property="Background" Value="Yellow"></Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <TextBox Width="200" Height="40"></TextBox>
    </Grid>
  </Window>