Click here to Skip to main content
13,860,817 members
Click here to Skip to main content
Add your own
alternative version


136 bookmarked
Posted 4 Jun 2006
Licenced CPOL

Creating a look-less custom control in WPF

, 4 Jun 2006
Rate this:
Please Sign up or sign in to vote.
In WPF, custom controls should be look-less. That means, that business logic and UI are strongly separated. When you create a control, you can provide a default template for the control, but anyone who uses the control can override it without touching the business logic.


In WPF, custom controls should be look-less. That means, that business logic and UI are strongly separated. When you create a control, you can provide a default template for the control, but anyone who uses the control can override it without touching the business logic.

In my sample, I will create a custom control for a simple clock, with a default template for a digital clock. In the application that uses the control, I will overwrite the template for the clock so that it will be displayed as an analog clock.

This sample was created with the February CTP.

Sample screenshot

Sample screenshot

Default template

Customized template

Creating the project

  • Create a "WinFX Windows Application". This application is used to test the custom control.
  • Create a "WinFX Custom Control Library". This library will contain the custom clock control.
  • Delete the file "UserControl1.xaml" in the control library.
  • Add a new custom control to the control library.
  • Add a reference to the control library in the Windows application project.

Creating the custom control

  • Add a DependencyProperty "DateTime" to the custom control. This property will always contain the actual date and time. Templates for this control can bind to this property. The PropertyChangedCallback is required to notify UI elements that the property has changed. Without this callback, bound controls would not be updated.

public DateTime DateTime
      return (DateTime)GetValue(DateTimeProperty);
   private set
      SetValue(DateTimeProperty, value);

public static DependencyProperty DateTimeProperty = 
        new PropertyMetadata(
            new PropertyChangedCallback(OnDateTimeInvalidated)));

public static readonly RoutedEvent DateTimeChangedEvent =

protected virtual void OnDateTimeChanged(DateTime oldValue, 
                                         DateTime newValue)
   RoutedPropertyChangedEventArgs<DateTime> args = new 
    RoutedPropertyChangedEventArgs<DateTime>(oldValue, newValue);
   args.RoutedEvent = Clock.DateTimeChangedEvent;

private static void OnDateTimeInvalidated(DependencyObject d, 
                    DependencyPropertyChangedEventArgs e)
   Clock clock = (Clock)d;
   DateTime oldValue = (DateTime)e.OldValue;
   DateTime newValue = (DateTime)e.NewValue;
   clock.OnDateTimeChanged(oldValue, newValue);

  • Add a Timer to the control to keep the "DateTime" property up to date.

    If you want to be able to update UI elements in your TimerElapsedEvent, you should use the DispatcherTimer class from the System.Windows.Threading namespace. Another option would be to invoke a delegate from the Control.Dispatcher object (this.Dispatcher.Invoke(...);).

using System.Windows.Threading;

namespace CustomControlLibrary
   public class Clock : Control
      private DispatcherTimer timer;

      static Clock()
             new FrameworkPropertyMetadata(typeof(Clock)));

      protected override void OnInitialized(EventArgs e)


         timer = new DispatcherTimer();
         timer.Interval = TimeSpan.FromMilliseconds(1000 - 
         timer.Tick += new EventHandler(Timer_Tick);

      private void Timer_Tick(object sender, EventArgs e)

         timer.Interval = TimeSpan.FromMilliseconds(1000 - 

      private void UpdateDateTime()
         this.DateTime = System.DateTime.Now;


Creating a default template for the custom control

  • Open the file "generic.xaml" in the "themes" folder. This file can contain a template for each custom control in the library.
  • Insert a template for the clock. In my sample, the current DateTime is displayed in a TextBlock control. Optionally, you could add a converter to the binding to format the DateTime property.

    xmlns="<A href="" target=_blank></A>"
    xmlns:x="<A href="" target=_blank></A>"
    <Style TargetType="{x:Type local:Clock}">
        <Setter Property="Template">
                 <ControlTemplate TargetType="{x:Type local:Clock}">
     <TextBlock Name="tblClock" Text="{Binding Path=DateTime, 
                RelativeSource={RelativeSource TemplatedParent}}" />

Using the custom control in an application

<Window x:Class="WindowsApplication.Window1"

    xmlns="<A href="" target=_blank></A>"
    xmlns:x="<A href="" target=_blank></A>"
    Title="WindowsApplication" Height="487" Width="412"
 <StackPanel HorizontalAlignment="Center">
  <customControl:Clock Name="customControlClock" />

Now the custom control is working.

Sample screenshot

Overriding the default template

By overriding the default template, it is possible to change the look and feel of the control completely.

  • Add a template for an analog clock to the resources of the StackPanel in "Window1.xaml". Furthermore, you will need some converters to convert the seconds, minutes, and hours of the actual date to an angle for the watch hands.
 <local:SecondsConverter x:Key="secondsConverter"/>
 <local:MinutesConverter x:Key="minutesConverter"/>
 <local:HoursConverter x:Key="hoursConverter"/>
 <local:WeekdayConverter x:Key="weekdayConverter"/>
 <Style x:Key="AnalogClock" TargetType="{x:Type customControl:Clock}">
  <Setter Property="Template">
    <ControlTemplate TargetType="{x:Type customControl:Clock}">
  • Draw the clock in the template. The template contains some ellipses and rectangles.
  • Bind the watch hands to the DateTime DependencyProperty of the custom control. As an angle of a RotateTransform cannot be bound to a DateTime datatype, you have to use a converter object.
<Rectangle x:Name="SecondHand" Canvas.Top="4" 

           Canvas.Left="49" Fill="Red" Width="1" Height="47">
  <RotateTransform Angle="{Binding Path=DateTime, 
       RelativeSource={RelativeSource TemplatedParent}, 
       Converter={StaticResource secondsConverter}}" 

       CenterX="0.5" CenterY="47"></RotateTransform>
  • Add converters for the watch hands in the code-behind file of "Window1.xaml". The SecondsConverter, for instance, uses the seconds date part of the DateTime property, and converts it to an angle for the second hand of the clock.
[ValueConversion(typeof(DateTime), typeof(int))]
public class SecondsConverter : IValueConverter
 public object Convert(object value, Type targetType, 
                       object parameter, CultureInfo culture)
  DateTime date = (DateTime)value;
  return date.Second * 6;
 public object ConvertBack(object value, Type targetType, 
                           object parameter, CultureInfo culture)
  return null;
  • Finally, you have to apply the new template to your clock control.
<customControl:Clock Name="customControlAnalogClock" 

                     Style="{StaticResource AnalogClock}" />

Now, the custom control is customized:

Sample screenshot


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Karin Huber
Software Developer software architects
Austria Austria
Hi, my name is Karin Huber. Since 1998 I have been working as a developer and IT consultant focusing on building database oriented web applications. In 2007 my friend Rainer and I decided that we want to build a business based on COTS (component off-the-shelf) software. As a result we founded "software architects".

These days we are offering our first version of the time tracking software called 'time cockpit'. You can find more information at

You may also be interested in...


Comments and Discussions

QuestionNice Stuff ! Pin
SkyRunner25-Jul-12 1:23
memberSkyRunner25-Jul-12 1:23 
GeneralMy vote of 5 Pin
Come Chão13-Jun-12 4:34
professionalCome Chão13-Jun-12 4:34 
QuestionOverwrite Pin
Sam Hobbs5-Mar-12 17:33
memberSam Hobbs5-Mar-12 17:33 
GeneralMy vote of 5 Pin
Wayne Gaylard8-Nov-11 2:46
mentorWayne Gaylard8-Nov-11 2:46 
QuestionAlthough I haven't read the article, but I believe that the content must be very NB Pin
batsword23-Sep-11 18:03
memberbatsword23-Sep-11 18:03 
GeneralCool Pin
thatraja8-Apr-11 19:44
protectorthatraja8-Apr-11 19:44 
GeneralRe: Cool Pin
Wayne Gaylard8-Nov-11 2:02
mentorWayne Gaylard8-Nov-11 2:02 
GeneralRe: Cool Pin
thatraja8-Nov-11 2:33
protectorthatraja8-Nov-11 2:33 
GeneralGreat Article! Pin
Fakher Halim10-Jun-10 13:15
memberFakher Halim10-Jun-10 13:15 
GeneralThanks Pin
Sayehboon10-Sep-09 3:24
memberSayehboon10-Sep-09 3:24 
GeneralGreat example! Demonstrates various aspects of WPF Pin
JoshMachin21-Jul-09 4:25
memberJoshMachin21-Jul-09 4:25 
GeneralBut what about... Pin
atm_grifter20-Aug-07 11:07
memberatm_grifter20-Aug-07 11:07 
GeneralRight to the point! Pin
Richard Houltz6-Aug-06 15:13
memberRichard Houltz6-Aug-06 15:13 
QuestionValueConversion usage Pin
Josh Smith18-Jul-06 11:14
memberJosh Smith18-Jul-06 11:14 
AnswerRe: ValueConversion usage Pin
Josh Smith1-Aug-06 6:50
memberJosh Smith1-Aug-06 6:50 
GeneralHey, first WPF article! Credits to you! Pin
Roland Hasenoehrl11-Jul-06 4:34
memberRoland Hasenoehrl11-Jul-06 4:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190214.1 | Last Updated 4 Jun 2006
Article Copyright 2006 by Karin Huber
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid