User Control vs Custom Control

Custom Control

  • Extends or creates an entirely custom, usually complex, control
  • Derives from Control or any of its subclasses
  • Usually has a pluggable interface
  • Usually defined in C# with a style inside the theme resource dictionary
  • Includes implementation and usually default template interface and style, but expected to be changed/skinned on by consumer

 User Control


Static vs dynamic resources


  • Always loaded on window/page load (even if not used)
  • Only ever loaded once
  • No forward referencing – must be declared above where it is used


  • Not loaded on window/page load (can improve start up time)
  • Reloaded each time the resource is changed (overhead to watch for changes)
  • Can only be used to set dependency properties

Dependency Properties

  • Only DependencyPropertys can be the target of binding (anything can be the source)
  • Static and sparely stored to save memory compared with if they were instance properties (as they are usually mostly set to their default value anyway)
  • .NET property wrappers are not called at runtime (but can be bound to at compile time), so any logic in getter/setter will be ignored
  • Provides useful functionality which can be utilised through the PropertyMetadata (default value and property changed callback)
  • Property Triggers (e.g. set background on mouse over) can only be used against Dependency Properties. (Data triggers can use .NET properties)
  • Setting FrameworkPropertyMetadataOptions.Inherits on Register means the value of the property will be inherited by children
  • ClearValue can be used to clear the local values

WPF Class Hierarchy

wpf hier


  • Standard .NET object base class. The only non WPF specific class in the hierarchy


  • Thread Affinity – Only the thread that created the object (i.e. the Dispatcher) can access it directly


  • Supports Dependency Properties
  • Provides GetValue and SetValue methods


  • Provides the method Freeze to transition the object into an immutable
  • Frozen objects do not need to spend resources on change notifications (which can be expensive for graphical objects containing unmanaged resources)
  • Frozen objects can be accessed across threads
  • Frozen objects can be copied without regenerating low level unmanaged objects


  • Has 2D visual rendering support
  • Appears in the visual tree


  • Defines nearly 100 UI events
  • Provides command, input binding and focus support
  • Contains layout logic


  • Builds WPF framework-level capabilities
  • Adds support for styling, data binding, resources, tooltips and context menus


  • Defines little behaviour, but is the ancestor of all controls – Button, ComboBox etc
  • Maintains a ControlTemplate in the Template property which defines appearance


  • Provides similar support as UIElement for inputs, focus, events etc.
  • But doesn’t provide its own rendering behaviour


  • Provides similar support as FrameworkElement for WPF framework-level capabilities (binding, tooltips, context menus etc)
  • But doesn’t participate in layout or rendering – must be used in a Visual object’s content

WPF Logical vs. Visual Trees

Logical Tree

  • Hierarchy of elements, usually defined in XAML (though can also be defined procedurally)
  • Excluding the visual elements provides a powerful abstraction:
    • Data oriented operations can be performed simply and quickly (e.g. only logical ancestors are searched for inherited resource definitions)
    • Developers can focus on the layout of elements and data and leave the visuals until later, or hand over to a pure UI developer

Visual Tree

  • Hierarchy of elements that actually get rendered
  • Only logical elements which derive from Visual (or Visual3D) appear in the visual tree
  • Usually only concerned with the visual tree when dealing with restyling (WPF’s look vs. logic separation)
  • Routed events traverse over the visual tree


A textual Label and textual ListBoxItem are distinct logical tree items, but have the same visual tree components.

Border -> ContentPresenter -> TextBox

Though each logical element will have different default property values.