Bookmark and Share Share...    Subscribe to this feed Feed   About Christian Moser  


How to Create a WPF Custom Control

This article gives you a step by step walktrough how to create a custom control in WPF. If you don't know the differences between a user control and a custom control, I recommend to read the article Custom Control vs. User Control first.

1. Define Requirements

Creating a custom control is quite simple in WPF. But the challenge is to do it the right way. So before you start creating a control try to answer the following questions:

  • What problem should my control solve?
  • Who will use this control? In which context and environment?
  • Can I extend or compose existing controls? Have a look at Existing Controls?
  • Should it be possible to style or template my control?
  • What design-time support should it have? In Expression Blend and Visual Studio?
  • Is it used in a single project, or part of a reusable library?

2. Create Project Structures

Create a new solution in VisualStudio and start with a WPF Custom Control Library and give it the name PopupControlLib. This is the place where our custom control comes in. Next we create an WPF Application and call it PopupControlTest. This is place where we test our control in a simple application.

  1. Create a new solution and start with a WPF Custom Control Library. Call it "PopupControlLib".
  2. Add a second project of type WPF Application to the solution and call it "PopupControlTest".
  3. Add a reference to the custom control library by using the "Add Reference" context menu entry on the "PopupControlTest" project item in the solution explorer.
  4. Rename the CustomControl1 to PopupControl.

3. Choose the right base class

Choosing the right base class is crucial and can save a lot of time! Compare the features of your control with existing controls and start with one that matches close. The following list should give you a good overview from the most leightweight to more heavyweight base types:

  • UIElement - The most lightweight base class to start from. It has support for LIFE - Layout, Input, Focus and Events.
  • FrameworkElement - Derives from UIElement and adds support for styling, tooltips and context menus. It is first base class that takes part in the logical tree and so it supports data binding and resource lookup.
  • Control - is the most common base class for controls (its name speaks for itself). It supports templates and adds some basic properties as Foreground, Background or FontSize.
  • ContentControl - is a control that has an additional Content property. This is often used for simple containers.
  • HeaderedContentControl - is a control that has an Content and a Header property. This is used for controls with a header like Expander, TabControl, GroupBox,...
  • ItemsControl - a control that has an additional Items collection. This is a good choice for controls that display a dynamic list of items without selection.
  • Selector - an ItemsControl whose items can be indexed and selected. This is used for ListBox, ComboBox, ListView, TabControl...
  • RangeBase - is the base class for controls that display a value range like Sliders or ProgressBars. It adds an Value, Minimum and Maximum property.

4. Override the Default Style

Controls in WPF separate behavior and appearance. The behavior is defined in code. The template is defined in XAML. The default template is by convention wrapped into a style that has an implicit key. That is is not a string - as usually - but a Type object of our control.

And that is excactly what we are doing in the static constructor. We are overriding the default value of the DefaultStyleKey property and set it to the Type object of our control.

 
static PopupControl()
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupControl),
        new FrameworkPropertyMetadata(typeof(PopupControl)));
}
 
 

5. Create a default Style

The style must be located by convention in a folder called "Themes" that must be located in the root of the control library project. In these folder we can provide different templates for each Windows theme. The name of these ResourceDictionaries must match the name of the windows theme. If we do not provide any theme-specific styles, we need to provide the fallback style located in the "Generic.xaml" file.

As we set the default value of the DefaultStylekey property to the Type object of our control, we must give our default style the same key to be found. This is done by leaving the x:Key attribute out. In this case WPF uses the type object from the TargetType property as key.

 
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <Style TargetType="{x:Type local:PopupControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:PopupControl}">
                    ... 
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 
</ResourceDictionary>
 
 

5. Add DependencyProperties

 
#region DependencyProperty Content
 
/// <summary>
/// Registers a dependency property as backing store for the Content property
/// </summary>
public static readonly DependencyProperty ContentProperty =
    DependencyProperty.Register("Content", typeof(object), typeof(PopupControl),
    new FrameworkPropertyMetadata(null, 
          FrameworkPropertyMetadataOptions.AffectsRender |
          FrameworkPropertyMetadataOptions.AffectsParentMeasure));
 
/// <summary>
/// Gets or sets the Content.
/// </summary>
/// <value>The Content.</value>
public object Content
{
    get { return (object)GetValue(ContentProperty); }
    set { SetValue(ContentProperty, value); }
}
 
#endregion
 
 

6. Map XML Namespace

Content follows...

7. Logical and Visual Children

  • Calling AddLogicalChild() creates the connection to navigate up the logical tree (bubbling).
  • Overriding GetLogicalChildren creates the connection to navigate down the logical tree (tunneling).

Content follows...





Last modified: 2009-07-17 13:14:56
Copyright (c) by Christian Moser, 2011.

 Comments on this article

Show all comments
Trey
Commented on 18.August 2009
Really cool article, I tried to do this with the WPF ribbon bar, but it's not working right for some reason. Does anyone know how to do this? I've looked on every website i could possibly think of and still haven't found what I'm looking for. Basically this is what i want to do/accomplish:

1. I have a pretty big project(around 70k lines ) that I'm trying to add a universal ribbon bar to the top of, each app being able to click through the tabs to get to the common functionality that will be available to that app

2. I have already created the ribbon(thanks to the walkthroughs of uxpassion.com ) that has a nice look and feel for what i want, but it is a WPF application(per the walkthrough) with XAML and a .cs file for all the method calls and functionality the XAML and ribbon require to work

3. I would like to know(if it's possible because i haven't found it anywhere on the web ) if i can use what i have now for my ribbon bar(code and all) and somehow place it at the top of all my different projects' pages so as to have the 2007 Office look no matter what you're looking at

I know this may be a noobie question that i just have overlooked or missed somewhere, but I would really appreciate anything that could help me acheive this(kind of on a deadline) so that my project will look professional

Thanks in advance!
Nayak14
Commented on 3.November 2009
can you pls also go ahead and explain how to use this control in the wpf application?
Harendra kumar
Commented on 5.January 2010
Nice ....
Keep in post new things.
lturek
Commented on 21.February 2010
Hi! Really nice how you're explaining all that things here! I have to say you helped me a lot by now and I will recomend you page!
To my question:
Is it possible to use an Usercontrol which is in the same project?
What I mean is a Solution with one project in it. In that project there is a window using Usercontrol1 which is also in the same project.
Hope you understand what I mean xD

Keep up your work, it's great!
lturek
Commented on 21.February 2010
Hi! Really nice how you're explaining all that things here! I have to say you helped me a lot by now and I will recomend you page!
To my question:
Is it possible to use an Usercontrol which is in the same project?
What I mean is a Solution with one project in it. In that project there is a window using Usercontrol1 which is also in the same project.
Hope you understand what I mean xD

Keep up your work, it's great!
lturek
Commented on 21.February 2010
Hi! Really nice how you're explaining all that things here! I have to say you helped me a lot by now and I will recomend you page!
To my question:
Is it possible to use an Usercontrol which is in the same project?
What I mean is a Solution with one project in it. In that project there is a window using Usercontrol1 which is also in the same project.
Hope you understand what I mean xD

Keep up your work, it's great!
lturek
Commented on 21.February 2010
I'm very sorry for the resend >_<
Lawrence
Commented on 26.February 2010
Your post is good and i need a stylish slider in wpf 3.5. How can i get that in wpf, if you give a post explaning like this. I ll be happy.
Sam
Commented on 28.February 2010
Excellent Post!. I am planning to create a windows Explorer 7 style search
control, which has a panel similar to list box and 4 search filters.
As I see it, when user clicks the search box a list box popups with last three searches. and a panel attached to list showing search filters. when user clicks one of the filters, say kind, then it opens a listbox with all possible search criterion.

Is it possible to do the same with wpf user control .





Dodge
Commented on 18.March 2010
Nice... Keep in post new things.
George Dmithrov
Commented on 9.April 2010
Excellent....! helped me verymuch.

Keep on posting new things.
learnwpf
Commented on 13.May 2010
can you post further content of this article
Mohamed
Commented on 4.June 2010
Please add more content to this article. May be how to modify the derived control.
Ravindra Kumar
Commented on 12.June 2010
great artical.
NewDeveloper
Commented on 24.July 2010
My User control has couple of fields to add a new user.
Can i use the same control to edit and search too ?
Tanner
Commented on 5.August 2010
This article is very helpful. I hope to see it completed soon. This site has been helpful in my wpf learning.

I wish to change the color of my custom control according to the value in a custom dependency property. However there are a few steps I still do not understand to get all that working together.
Alex 75
Commented on 14.October 2010
"The name of these ResourceDictionaries must match the name of the windows theme"
I've a custom control, not a Window ... what name I've to use?

"<Style TargetType="{x:Type local:PopupControl}">"
local is an undeclared namespace.

Alessandro
How to...
Commented on 26.October 2010
Please provide some tips to implement this featrue...
John
Commented on 17.November 2010
Article is incomeplete. Couldnt find it useful. Sorry
VijayS
Commented on 29.November 2010
Very Help ful for beginers....
x
Commented on 6.January 2011
I dont think it is in no way helpful for beginners. Incomplete articles. total waste of time.
Wesley De...
Commented on 28.January 2011
How much longer untill you finish what you started? This was posted June 2009???
!
Commented on 31.January 2011
Looks like this\'ll be a good article - when its finished.
Yuri
Commented on 24.February 2011
I've created this control, what then? how to create realy custom/useful behavior and view for this control? Can we get some real example?
!!
Commented on 28.February 2011
worthless

Name
E-Mail (optional)
Comment