Monday, January 14, 2013

WPF DatePicker Control Style

How to style a WPF Date Picker control?

The WPF controls were hierarchical controls and most likely implements what other controls were implemented (inherited the styles and functions) as follow through how the User Interface reacts based on the events made by the end-user in your application. Same of how does WPF DatePicker control was implemented.

For your MSDN reference, please visit this link.

Styling WPF DatePicker control is not easy perhaps a slight complex than what of other controls in WPF.


First, you need to know how the WPF DatePicker control implements its PARTS. Once you understand how WPF DatePicker control implemented its PART, you need to drill down and determine what kind of control the PART was used in the WPF DatePicker control.

As per referenced, the parts of WPF DatePicker control were follow (based from MSDN):

Part

Type
PART_RootFrameworkElement
PART_TextBoxDatePickerTextBox
PART_ButtonButton
PART_PopupPopup

So, we will start the main Style of DatePicker control (see below).

<Style x:Key="styleDatePicker" TargetType="{x:Type DatePicker}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DatePicker}">
                <Grid x:Name="PART_Root">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <DatePickerTextBox x:Name="PART_TextBox"
                                       BorderBrush="{TemplateBinding BorderBrush}"
                                       BorderThickness="{TemplateBinding BorderThickness}"
                                       HorizontalContentAlignment="Stretch"
                                       Padding="{TemplateBinding Padding}"
                                       VerticalContentAlignment="Center"
                                       Visibility="Visible"
                                       Grid.Column="0">
                    </DatePickerTextBox>
                    <Button x:Name="PART_Button">
                        <Button.Style>
                            <Style TargetType="{x:Type Button}">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Button}">
                                            <!-- Do button template and triggers here -->
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Button.Style>
                    </Button>
                    <Popup x:Name="PART_Popup" StaysOpen="False" AllowsTransparency="True" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Above is a simple Style that can be used as a template when designing the WPF DatePicker control. You'll notice that the PART_Root were used a as top level control of the template. In WPF we need to implement the actual orders of how the WPF DatePicker control implemented them.

PART_TextBox: It is a part of the WPF DatePicker control of type DatePickerTextBox that holds the input control (free text control) in your DatePicker.

PART_Button: It is a part of the WPF DatePicker control of type Button that holds the actual button control that user is clicked when he/she needs to expand/collapsed the Calendar of the WPF DatePicker control.

PART_Popup: It is a part of the WPF DatePicker control of type Popup that holds the container of the Calendar control of the WPF DatePicker control.

Implementing WPF Date Picker control PART Styles

Let's start with the the chronological order implementation of WPF DatePicker control PARTS:

1. WPF Date Picker Control TextBox

Since it is a TextBox control type, we need to do the TextBox style.

<Style x:Key="styleDatePickerTextBox" TargetType="{x:Type DatePickerTextBox}">
    <Setter Property="Background" Value="Transparent"></Setter>
    <Setter Property="BorderBrush" Value="Transparent"></Setter>
    <Setter Property="BorderThickness" Value="0"></Setter>
    <Setter Property="IsEnabled" Value="True"></Setter>
    <Setter Property="IsReadOnly" Value="False"></Setter>
</Style>

You will notice we had referenced the TargetType property to TextBox control type and simply set the other important properties I like to modify. You will notice that nothing is different but only to disable the editing by setting the IsReadOnly property to False.

2. WPF Date Picker Control Button

This is the section where the user is clicking to collapse/expand the Calendar control.

<Button x:Name="PART_Button" VerticalAlignment="Stretch">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="OverridesDefaultStyle" Value="True"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Name="buttonImage"
                               Height="Auto"
                               HorizontalAlignment="Center"
                               Margin="1"
                               Source="../images/datepicker_unselected.png"
                               Stretch="Fill"
                               VerticalAlignment="Stretch"
                               Width="{Binding Path=Height, RelativeSource={RelativeSource Mode=Self}}">
                        </Image>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="buttonImage"
                                        Property="Source"
                                        Value="../images/datepicker_selected.png"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

So what the above style is doing? Based on the implementation of the button template and how the triggers reacts on the events. It simply display the resource image "../images/datepicker_unselected.png" as a default value.

Once the user mouse hovered the image control, the implemented "Trigger" will be triggered to set the Source property value of the image to value "../images/datepicker_selected.png".

3. WPF Date Picker Control PopUp

This is the section where the Calendar control is being placed/contained.

<Popup x:Name="PART_Popup" StaysOpen="False" AllowsTransparency="True" />

The above style for Popup control is to only implements and change the StaysOpen and AllowsTransparency property on how it reacts on the user interaction against the control and how the transparency being applied in the rendering.

4. WPF Date Picker Control Calendar

In the Calendar control, we have three important style needs to implement (if you want to override the style of each item inside it).

CalendarButtonStyle: The style will be applied to the month/year button of the Calendar control.

CalendarDayButtonStyle: The style will be applied to the day's button of the the Calendar control.

CalendarItemStyle: The style will be applied to the actual Calendar control.

For your reference on how to style Calendar control, please visit WPF Calendar Style blog.

5 comments:

  1. I used your example and it does increase the size of the Calendar. In my project in VS 2012 the image quality of the calendar is really grainy and poor. If I try the same in Blend it is crisp. Do you have any ideas as to why this would be so?

    ReplyDelete
    Replies
    1. I'm having the same problem. How can resolve?

      Delete
  2. Good Article...keep posting

    ReplyDelete
  3. Hi,
    im new in wpf, can u show me how to apply this style on DatePicker control. i mean with Datepicker xaml too.
    thanks

    ReplyDelete

Place your comments and ideas