Style Button in WPF

Introduction

WPF is a presentation system for building Windows based applications having an attractive User Interface (UI). This is not only in Windows-based or standalone applications, this also works in browser-based applications. WPF is an engine that is a vector-based rendering engine that uses modern graphic hardware. WPF has many features and those features make WPF popular. Some of the feature are the following: 

  • Direct 3D
  • Data Binding
  • Media Service
  • Templates
  • Animations
  • Imaging
  • Documents
  • Text

In this article we will learn about animated buttons using WPF. We will use style and a template to create a customized button. This customized button design part is written in the Extensible Application Markup Language (XAML). We will be learning step-by-step.

Create a Basic Button in WPF

step 1 :
Open the Visual Studio
           
Step 2 :
Select a new WPF project. Click the file menu and select New then click on the project. Find the Windows Desktop WPF Application template.  

NewProject

Step 3
:  Change the default Grid element into StackPanel and use the default buttons inside the StackPanel, as in the following code:

  1. <Window x:Class="WpfApplication1.MainWindow"  
  2.   
  3.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  4.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  5.         Title="MainWindow" Height="300" Width="300" Background="Black">  
  6.     <StackPanel HorizontalAlignment="Left">  
  7.         <Button>Button 1</Button>  
  8.         <Button>Button 2</Button>  
  9.         <Button>Button 3</Button>  
  10.         <Button>Button 3</Button>  
  11.    
  12.     </StackPanel>  
  13. </Window>  

Output:

outputScreen1

Set Basic Properties

We will set the basic properties for the Button. We will use an Application resource to set the property. It is similar to Cascading Style Sheets (CSS) in any web pages. However application resources are much more powerful than CSS. Let's try to implement that. 

  •  Define an Application.Resources block

    Open the app.xaml file and add the definition of the Application.Resources if it is not present in the app.xaml file.
    1. <Application x:Class="Button.App"  
    2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    4.              StartupUri="MainWindow.xaml">  
    5.     <Application.Resources>  
    6.            
    7.     </Application.Resources>  
    8. </Application>  

    Application.Resources enables the resources to be used any where in the application. 

  •   Define basic property value

    As we can see the basic property for the target control. This time our target control is Button and we will set the width and margin for that, as we can see in the following code. 
    1. <Application.Resources>  
    2.         <Style TargetType="Button">  
    3.         <Setter Property="Width" Value="90"/>  
    4.             <Setter Property="Margin" Value="10"/>  
    5.         </Style>  
    6.     </Application.Resources>  
    OutputScreen2  
  • Set a style property value to a resource 
    1. <Application.Resources>  
    2.       <LinearGradientBrush x:Key="GrayBlueGardientBrush"  
    3.                             StartPoint="0,0" EndPoint="1,1">  
    4.            <GradientStop Color="DarkCyan" Offset="0"/>  
    5.            <GradientStop Color="#CCCCFF" Offset="0.5"/>  
    6.            <GradientStop Color="DarkCyan" Offset="1"/>  
    7.              
    8.        </LinearGradientBrush>  
    9.        <Style TargetType="{x:Type Button}">  
    10.            <Setter Property="Background" Value="{StaticResource GrayBlueGardientBrush}"/>  
    11.            <Setter Property="Width" Value="80"/>  
    12.            <Setter Property="Margin" Value="10"/>  
    13.        </Style>  
    14.    </Application.Resources>  
    As in the code above we have set some color (gradient color) inside the button. 

        OutputScreen3

Using Template Defines the Look of the Button

We will be using a template for the button. Templates generally give us a different look. There are various templates to make our button a unique look. Always remember we need to use a template inside the style tag.

  • Set up the template

    A button has a template property, we will define the template property value just like the other property values and set the style in the setter tag.
    1. <Application.Resources>  
    2.        <LinearGradientBrush x:Key="GrayBlueGardientBrush"  
    3.                              StartPoint="0,0" EndPoint="1,1">  
    4.             <GradientStop Color="DarkCyan" Offset="0"/>  
    5.             <GradientStop Color="#CCCCFF" Offset="0.5"/>  
    6.             <GradientStop Color="DarkCyan" Offset="1"/>  
    7.               
    8.         </LinearGradientBrush>  
    9.          <Style TargetType="{x:Type Button}">  
    10.             <Setter Property="Background" Value="{StaticResource GrayBlueGardientBrush}"/>  
    11.             <Setter Property="Width" Value="80"/>  
    12.             <Setter Property="Margin" Value="10"/>  
    13.             <Setter Property="Template">  
    14.                 <Setter.Value>  
    15.                       
    16.                 </Setter.Value>  
    17.                  
    18.             </Setter>  
    19.         </Style>  
    20.     </Application.Resources>  
  • Alter button presentation

    A DockPanel is used to host the ContentPresenter of the button and ContentPresenter will help to display the content of the button. We will make rounded edges for the button. 
    1. <Setter.Value>  
    2.                     <ControlTemplate TargetType="Button">  
    3.                         <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">  
    4.                             <Rectangle x:Name="outerRectangle"    
    5.                                        HorizontalAlignment="Stretch"    
    6.                                        VerticalAlignment="Stretch"    
    7.                                        Stroke="{TemplateBinding Background}"    
    8.                                        RadiusX="20" RadiusY="20" StrokeThickness="5"    
    9.                                        Fill="Transparent" />  
    10.                              <Rectangle x:Name="innerRectangle"    
    11.                                         HorizontalAlignment="Stretch"    
    12.                                         VerticalAlignment="Stretch" Stroke="Transparent"    
    13.                                         StrokeThickness="20"    
    14.                                         Fill="{TemplateBinding Background}"    
    15.                                         RadiusX="20" RadiusY="20"   />  
    16.                             <DockPanel Name="myContentPresenterDockPanel">  
    17.                                 <ContentPresenter x:Name="myContentPresenter" Margin="20"    
    18.                                         Content="{TemplateBinding  Content}"    
    19.                                         TextBlock.Foreground="Black" />  
    20.                             </DockPanel>  
    21.                         </Grid>  
    22.                     </ControlTemplate>  
    23.                 </Setter.Value>  
    OutputScreen4
     
  • Add a glasseffect to the template

    The glasseffect control is used to fill a rectangle that we insert into the grid of the template button. For that we need to create a resource. That resource will create the glass gradient effect.
    1. <Application.Resources>  
    2.        <GradientStopCollection x:Key="MyGlassGradientStopsResource">  
    3.            <GradientStop Color="WhiteSmoke" Offset="0.2" />  
    4.            <GradientStop Color="Transparent" Offset="0.4" />  
    5.            <GradientStop Color="WhiteSmoke" Offset="0.5" />  
    6.            <GradientStop Color="Transparent" Offset="0.75" />  
    7.            <GradientStop Color="WhiteSmoke" Offset="0.9" />  
    8.            <GradientStop Color="Transparent" Offset="1" />  
    9.        </GradientStopCollection>  
    10.        <LinearGradientBrush x:Key="GrayBlueGardientBrush"  
    11.                             StartPoint="0,0" EndPoint="1,1">  
    12.            <GradientStop Color="DarkCyan" Offset="0"/>  
    13.            <GradientStop Color="#CCCCFF" Offset="0.5"/>  
    14.            <GradientStop Color="DarkCyan" Offset="1"/>  
    15.   
    16.        </LinearGradientBrush>  
    17.        <Style TargetType="{x:Type Button}">  
    18.            <Setter Property="Background" Value="{StaticResource GrayBlueGardientBrush}"/>  
    19.            <Setter Property="Width" Value="80"/>  
    20.            <Setter Property="Margin" Value="10"/>  
    21.            <Setter Property="Template">  
    22.                <Setter.Value>  
    23.                    <ControlTemplate TargetType="{x:Type Button}">  
    24.                        <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"  
    25.                              ClipToBounds="True">  
    26.   
    27.                            <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"   
    28.                                       VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"   
    29.                                       RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />  
    30.   
    31.                            <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"   
    32.                                       VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20"   
    33.                                       Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />  
    34.   
    35.                            <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"   
    36.                                       VerticalAlignment="Stretch"   
    37.                                       StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"   
    38.                                       Fill="{StaticResource GrayBlueGardientBrush}"   
    39.                                       RenderTransformOrigin="0.5,0.5">  
    40.                                <Rectangle.Stroke>  
    41.                                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">  
    42.                                        <LinearGradientBrush.GradientStops>  
    43.                                            <GradientStop Offset="0.0" Color="LightBlue" />  
    44.                                            <GradientStop Offset="1.0" Color="Gray" />  
    45.                                        </LinearGradientBrush.GradientStops>  
    46.                                    </LinearGradientBrush>  
    47.                                </Rectangle.Stroke>  
    48.   
    49.                                <Rectangle.RenderTransform>  
    50.                                    <TransformGroup>  
    51.                                        <ScaleTransform />  
    52.                                        <RotateTransform />  
    53.                                    </TransformGroup>  
    54.                                </Rectangle.RenderTransform>  
    55.   
    56.                                <Rectangle.BitmapEffect>  
    57.                                    <BevelBitmapEffect />  
    58.                                </Rectangle.BitmapEffect>  
    59.                            </Rectangle>  
    60.                            <DockPanel Name="myContentPresenterDockPanel">  
    61.                                <ContentPresenter x:Name="myContentPresenter" Margin="20"   
    62.                                                  Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />  
    63.                            </DockPanel>  
    64.                        </Grid>  
    65.                    </ControlTemplate>  
    66.               </Setter.Value>  
    67.                
    68.              </Setter>  
    69.        </Style>  
    70.    </Application.Resources>  

    OutputScreen5

Create Button Interactivity

Interactivity means mouse-over, mouse-leave, click and so on. For setting the button interactivity we need to use a property trigger and an event trigger. To define the trigger within our template or style, we need to set the property "condition", such as the IsMouseOver equal to true. The procedure to create the button interactivity is as the following.

  • Add template triggers : Add the highlighted markup to our template.

    1. <Setter.Value>  
    2.                      
    3.                         <ControlTemplate TargetType="{x:Type Button}">  
    4.                             <Grid Width="{TemplateBinding Width}"   
    5.       Height="{TemplateBinding Height}" ClipToBounds="True">  
    6.    
    7.                                 <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"   
    8.       VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"   
    9.       RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />  
    10.    
    11.                                 <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"   
    12.         VerticalAlignment="Stretch" Stroke="Transparent"   
    13.         StrokeThickness="20"   
    14.         Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20"   
    15.       />  
    16.    
    17.                                 <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"  
    18.         VerticalAlignment="Stretch"  
    19.         StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"  
    20.         Fill="{StaticResource  GrayBlueGardientBrush}"  
    21.         RenderTransformOrigin="0.5,0.5">  
    22.                                     <Rectangle.Stroke>  
    23.                                         <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">  
    24.                                             <LinearGradientBrush.GradientStops>  
    25.                                                 <GradientStop Offset="0.0" Color="LightBlue" />  
    26.                                                 <GradientStop Offset="1.0" Color="Gray" />  
    27.                                             </LinearGradientBrush.GradientStops>  
    28.                                         </LinearGradientBrush>  
    29.                                     </Rectangle.Stroke>  
    30.    
    31.                                     <Rectangle.RenderTransform>  
    32.                                         <TransformGroup>  
    33.                                             <ScaleTransform />  
    34.                                             <RotateTransform />  
    35.                                         </TransformGroup>  
    36.                                     </Rectangle.RenderTransform>  
    37.                                      <Rectangle.BitmapEffect>  
    38.                                         <BevelBitmapEffect />  
    39.                                     </Rectangle.BitmapEffect>  
    40.                                 </Rectangle>  
    41.    
    42.                                 <DockPanel Name="myContentPresenterDockPanel">  
    43.                                     <ContentPresenter x:Name="myContentPresenter" Margin="20"   
    44.           Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />  
    45.                                 </DockPanel>  
    46.                             </Grid>  
    47.    
    48.                             <ControlTemplate.Triggers>  
    49.                            </ControlTemplate.Triggers>  
    50.                         </ControlTemplate>  
    51.                     </Setter.Value>   
  • Add property triggers : Add the code to the ControlTemplate.Triggers block. 
    1. <ControlTemplate.Triggers>  
    2.                             <Trigger Property="IsMouseOver" Value="True">  
    3.    
    4.                                 
    5.                                 <Setter Property ="Rectangle.Stroke"               TargetName="outerRectangle"   
    6.       Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />  
    7.    
    8.                                  
    9.                                 <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />  
    10.    
    11.                                 
    12.                                 <Setter Property="ContentPresenter.BitmapEffect"    
    13.       TargetName="myContentPresenter">  
    14.                                     <Setter.Value>  
    15.                                         <BlurBitmapEffect Radius="1" />  
    16.                                     </Setter.Value>  
    17.                                 </Setter>  
    18.                             </Trigger>  
    19. </ControlTemplate.Triggers>  

    OutputScreen6
     

  • Add a focus trigger : Adding some setter for the focus on button click
    1. <ControlTemplate.Triggers>  
    2.                             <Trigger Property="IsMouseOver" Value="True">  
    3.                                 <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"  
    4.                                         Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />  
    5.    
    6.                                 <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />  
    7.                                 <Setter Property="ContentPresenter.BitmapEffect"       TargetName="myContentPresenter">  
    8.                                     <Setter.Value>  
    9.                                         <BlurBitmapEffect Radius="1" />  
    10.                                     </Setter.Value>  
    11.                                 </Setter>  
    12.                             </Trigger>  
    13.                                 <Trigger Property="IsFocused" Value="true">  
    14.                                 <Setter Property="Rectangle.Opacity" Value="1"       TargetName="glassCube" />  
    15.                                 <Setter Property="Rectangle.Stroke" TargetName="outerRectangle"   
    16.                                         Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />  
    17.                                 <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />  
    18.                             </Trigger>  
    19.                         </ControlTemplate.Triggers>  
  • Add animations for MouseEnter and MouseLeave
    1. <EventTrigger RoutedEvent="Mouse.MouseEnter">  
    2.                                 <EventTrigger.Actions>  
    3.                                     <BeginStoryboard Name="mouseEnterBeginStoryboard">  
    4.                                         <Storyboard>  
    5.      
    6.                                             <DoubleAnimation Storyboard.TargetName="glassCube"    
    7.                                                              Storyboard.TargetProperty=   
    8.                                                              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].                                                                          (ScaleTransform.ScaleX)"   
    9.                                                              By="-0.1" Duration="0:0:0.5" />  
    10.    
    11.                                             <DoubleAnimation Storyboard.TargetName="glassCube" Storyboard.TargetProperty=   
    12.                                                              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].                                                                          (ScaleTransform.ScaleY)"    
    13.                                                              By="-0.1" Duration="0:0:0.5" />  
    14.                                         </Storyboard>  
    15.                                     </BeginStoryboard>  
    16.                                 </EventTrigger.Actions>  
    17.                             </EventTrigger>  
    18.                             <EventTrigger RoutedEvent="Mouse.MouseLeave">  
    19.                                 <EventTrigger.Actions>  
    20.    
    21.                                     <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />  
    22.                                 </EventTrigger.Actions>  
    23.                             </EventTrigger>  
  • Add an animation for when the button is clicked
    1. <EventTrigger RoutedEvent="Mouse.MouseLeave">  
    2.                                 <EventTrigger.Actions>  
    3.                                     <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />  
    4.                                 </EventTrigger.Actions>  
    5.                             </EventTrigger>  
    6.                             <EventTrigger RoutedEvent="Button.Click">  
    7.                                 <EventTrigger.Actions>  
    8.                                     <BeginStoryboard>  
    9.                                         <Storyboard>  
    10.                                             <DoubleAnimation Storyboard.TargetName="glassCube"    
    11.           Storyboard.TargetProperty=   
    12.           "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"    
    13.           By="360" Duration="0:0:0.5" />  
    14.                                         </Storyboard>  
    15.                                     </BeginStoryboard>  
    16.                                 </EventTrigger.Actions>  
    17.   </EventTrigger>  

Summary

In this article we learned various styles for a button, set the basic properties for the button that the entire application will use. We have also learned how to create resources like gardiants to be used for property values of the style setters and we have customized the behavior of a button in response to user actions, like mouseEnter, MouseLeave and click that all have animated effects.