Saturday, August 6, 2011

CREATING A CUSTOM TIMEPICKER CONTROL IN WPF 4.0

Download the Source Code Here

Introduction

I was working on an application, Time Watcher 5.0, and I needed to use a TimePicker control which was not provided along with controls in WPF 4.0. There are several third party TimePicker controls but I was not satisfied with their ‘mechanism of action and behaviour’. Below are the steps I took to create my own custom TimePicker control knowing that it will benefit a lot of people by sharing the process.


Please Note This!

Please note that this may not be the accurate way to create a custom control because no property of the control was exposed but it will give an insight on how to use existing controls to design your own custom controls.

In this demonstration, I’ll be using Expression Blend 4. Now let get to business!

STEP 1 (Designing the Control)


In Expression Blend, do the following

1. Add a Grid to the LayoutRoot (This grid serves as a container)

2. Add a StackPanel to the Grid you just added, set the orientation to ‘horizontal’, Vertical Alignment and Horizontal alignment to ‘stretch’

3. Add a Toggle Button to the StackPanel , right click on the Toggle Button and click Edit Template -> Edit a copy

4. Select the ContentPresenter and cut, select the Chrome and delete.

5. Select Template above and add a Grid to it from Asset

6. Select the Grid and paste the ContentPresenter inside the Grid, you should have something similar to label 6 in the picture below:

7. Select Template above and add a Grid to it from Asset

8. Go to the Trigger tab, add a new property and set the “IsChecked = true”

9. Select the Grid and change the background colour to “#FF919191”

10. Return scope to windows





11. Rename the Toggle Button to HrBtn

12. Select the Toggle Button and add a TextBlock to it.

13. Rename the TextBlock to HrTxt

14. Select the Toggle Button and copy

15. Paste three (3) copies of the Toggle Button inside the StackPanel

16. Rename the new copies of the Toggle Button as ‘MinBtn’, ‘SecBtn’ and ‘AmPmBtn’ respectively

17. Rename the TextBlock inside each Toggle Button as ‘MinTxt’, ‘SecTxt’ and ‘AmPmTxt’ respectively

18. Add two other TextBlock to the StackPanel and set their Text Property as “:”

19. Add two Buttons to the StackPanel and rename them as ‘upBtn’ and ‘downBtn’ respectively. Set their Text Property to ‘Up’ and ‘Down’ respectively.

20. Rearrange your Timeline to resemble the one shown below:



Your control should look similar to this:




STEP 2 (CODING YOUR CONTROL)

Under the upBtn_Click Event Handler, add the following code::

if (HrBtn.IsChecked == true)
   {
    int hour = int.Parse(HrTxt.Text);
    
    if (hour == 12)
     hour = hour - hour;
    
    hour++;
    
    HrTxt.Text = hour.ToString();
   }
   else if (MinBtn.IsChecked == true)
   {
    int min = int.Parse(MinTxt.Text);
    
    if (min == 59)
     min = -1;
    
    min++;
    
    if (min.ToString().Length == 1)
    {
     MinTxt.Text = "0" + min.ToString();
    }
    else
    {
     MinTxt.Text = min.ToString();
    }
   }
   else if (SecBtn.IsChecked == true)
   {
    int sec = int.Parse(SecTxt.Text);
    
    if (sec == 59)
     sec = -1;
    
    sec++;
    
    if (sec.ToString().Length == 1)
    {
     SecTxt.Text = "0" + sec.ToString();
    }
    else
    {
     SecTxt.Text = sec.ToString();
    }
   }
   else if (AmPmBtn.IsChecked == true)
   {
    if(AmPmTxt.Text == "AM")
    {
     AmPmTxt.Text = "PM";
    }
    else
    {
     AmPmTxt.Text = "AM";
    }
   }

  

Under the downBtn_Click Event Handler, add the following code:

if (HrBtn.IsChecked == true)
   {
    int hour = int.Parse(HrTxt.Text);
    
    if (hour == 1)
     hour = 13;
    
    hour--;
    
    HrTxt.Text = hour.ToString();
   }
   else if (MinBtn.IsChecked == true)
   {
    int min = int.Parse(MinTxt.Text);
    
    if (min == 0)
     min = 60;
    
    min--;
    
    
    if (min.ToString().Length == 1)
    {
     MinTxt.Text = "0" + min.ToString();
    }
    else
    {
     MinTxt.Text = min.ToString();
    }
   }
   else if (SecBtn.IsChecked == true)
   {
    int sec = int.Parse(SecTxt.Text);
    
    if (sec == 0)
     sec = 60;
    
    sec--;
    
    
    if (sec.ToString().Length == 1)
    {
     SecTxt.Text = "0" + sec.ToString();
    }
    else
    {
     SecTxt.Text = sec.ToString();
    }
   }
   else if (AmPmBtn.IsChecked == true)
   {
    if(AmPmTxt.Text == "AM")
    {
     AmPmTxt.Text = "PM";
    }
    else
    {
     AmPmTxt.Text = "AM";
    }
   }

  



If you can have your way with graphics, you can skin your control as it suits you. The final control of Time Watcher 5.0 application looks like this:



Use string formatting to convert each text into a single string and you can go ahead to use the DateTime class to convert the resulting string to the appropriate time format.

Using the DateTime class you can also combine the date from a DatePicker together with the TimePicker to form a complete Date-Time like that of WinForm such as “Saturday, August 6, 2011 12:00:00 AM”


Download the Source Code Here