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 is an introductory article on how to create custom controls for your application from a designer's point of view. This article will give an insight
on how to use existing controls to design your own custom controls, and recommendations on how to create reusable custom controls (with registered properties) are provided
at the end of this article.
In this demonstration, I'll be using Expression Blend 4. Now let's get to business!
Step 1 - Designing the control
In Expression Blend 4, do the following:
Layout
- Add a
Grid to the LayoutRoot (This is the parent container)
- Set the background colour of the
Grid to "#000000"
- Add a
StackPanel to the Grid you just added
- Set the orientation to "horizontal"
- Set the vertical alignment and horizontal alignment to "stretch"
- Add a
ToggleButton to the StackPanel
Your layout should look similar to this:

Figure 1
ToggleButton - Edit template
- Right click on the
ToggleButton and click Edit Template -> Edit a copy.
- Select
ContentPresenter and cut, select the Chrome, and delete.
- Select
Template in the Timeline and add a Grid to it from Asset.
- Select the
Grid and paste the ContentPresenter inside it (your Object and Timeline panel should look like figure 2(a)).
- Make sure the
Template node is selected in the Timeline.
- Go to the Trigger tab, add a new property (see Figure 2b).
- Change the property to
IsChecked and set the value to "true" (see Figure 2b).
- Now select the
Grid inside the Template and change the background colour to "#FF919191".
- Return scope to Window.


Figure 2
Layout - A finishing touch
- Rename the
ToggleButton to 'HrBtn'.
- Select the
ToggleButton and add a TextBlock to it.
- Rename the
TextBlock to HrTxt and set the foreground colour to "#FFFFFFFF".
- Select the
ToggleButton and copy.
- Paste three copies of the
ToggleButton inside the StackPanel.
- Rename the new copies of the
ToggleButton as MinBtn, SecBtn, and AmPmBtn.
- Rename the
TextBlock inside each ToggleButton as MinTxt, SecTxt, and AmPmTxt.
- Add two other
TextBlocks to the StackPanel and set their Text property as ':'.
- Add two
Button controls to the StackPanel and rename them as upBtn and downBtn.
- Set the
Text property of these Button controls to 'Up' and 'Down', respectively.
- 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 have good hands in design especially in Expression Blend, you can skin your control as it suits you. The final control
of Time Watcher 5.0 application looks like this:

On a final note
When creating a reusable ontrol, it must be "skinable"; the use of the WPF commanding model
(see Commanding Overview) is also better than raising clicked events if you are creating a control
for reuse. A bindable DateTime or TimeSpan property will also enable users of this control to bind to it.
Thanks to Keith Barrow for this contribution.
Recommendations
For further readings on how to create a custom control and add dependency properties, I recommend Create a WPF
Custom Control, Part 1 and Create a WPF Custom Control, Part 2
by David Veeneman.