What's the difference betwen a UserControl and a ContentControl?

Mark A. Donohoe picture Mark A. Donohoe · Sep 13, 2013 · Viewed 10.7k times · Source

According to all of the documentation, when you're creating a non-lookless control, you're supposed to subclass UserControl. However, UserControl is a simple subclass of ContentControl but it doesn't appear to add anything to it, interface-wise. As such, you can take that designer-generated code and change the base class to ContentControl and it appears to still work exactly the same.

So what's the point of UserControl over ContentControl?

Update:

For those who keep answering Visual Studio treats them differently, I'd argue that isn't the case. Try it! Create a new UserControl in Visual Studio, then in the resulting XAML file, change the root tag to ContentControl. Then in the associated class file, change the base class to ContentControl or simply delete it as I have done here (see the note) and you'll see it appears to work exactly the same, including full WYSIWYG designer support.

Note: You can delete the base class from the code-behind because it's actually a partial class with the other 'part' of the class being created by the XAML designer via code-generation. As such, the base class will always be defined as the root element of the XAML file, so you can simply omit it in the code-behind as it's redundant.

Here's the updated XAML...

<ContentControl x:Class="Playground.ComboTest.InlineTextEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <TextBlock Text="Success" />

</ContentControl>

...and the associated class file...

namespace Playground.ComboTest {

    public partial class InlineTextEditor {

        public InlineTextEditor()
            => InitializeComponent();
    }
}

Answer

Adam Caviness picture Adam Caviness · Jan 18, 2017

UserControls are a good fit for aggregating existing controls when you don't need to provide the consumer a ControlTemplate. This means that UserControls are not lookless. Why not just use ContentControl as it can have coupled XAML like a UserControl and the implementation looks similar to UserControl? Well, there are several important technical differences you must know:

  1. UserControls set themselves as the source to RoutedEvents raised by elements within them. This means that when an element outside the UserControl receives a bubbled event, the Source is the UserControl, not the thing you interacted within the UserControl. In the philosophical sense of what you often hear about UserControls, "It's for aggregating existing controls", this makes sense as you want the parent container element to think of your UserControl as a single unit. For example, your UserControl contains a button that the user clicks and the Grid that contains your UserControl instance receives the MouseLeftButtonUp event but the Button is not the Source of the event, your UserControl is.
  2. UserControl sets Focusable and IsTabStop to false. You can see the philosophy demonstrating itself again here as we don't want a grouping of existing controls to be Focusable.
  3. UserControl sets HorizontalAlignment and VerticalAlignment to Stretch. A ContentControl would automatically be set to Left and Top.
  4. UserControl's own AutomationPeer implementation allows you to change VisualStates via VisualStateManager.GoToState(). ContentControl requires the VisualStateGroups to be at the top-level and you must call them with VisualStateManager.GoToElementState().
  5. UserControl's own ControlTemplate wraps your content in a Border. This again makes sense when thinking of the philosophical use case for UserControl.
  6. UserControl's own ControlTemplate provides more TemplateBindings than ContentControl. This is kind of a recapitulation of some above items but explains how they are possible. Recall that UserControl provides a Border so that relates to some of these free TemplateBindings you see below. This enables respect for BorderBrush, BorderThickness, Background and Padding properties on your control that would otherwise not work with just a ContentControl. For example, if you just derive your control from ContentControl and set the Background property on the root ContentControl element it will not work because the ControlTemplate of ContentControl has no TemplateBinding for Background. Of course you could set the Background property on the child content element that wraps your desired elements, like a Grid, but that isn't ideal IMO.

ContentControl's ControlTemplate

<ControlTemplate TargetType="ContentControl">
  <ContentPresenter
   Content="{TemplateBinding ContentControl.Content}"
   ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
   ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" />
</ControlTemplate>

UserControl's ControlTemplate

<ControlTemplate TargetType="UserControl">
  <Border BorderBrush="{TemplateBinding Border.BorderBrush}"
   BorderThickness="{TemplateBinding Border.BorderThickness}"
   Background="{TemplateBinding Panel.Background}"
   Padding="{TemplateBinding Control.Padding}"
   SnapToDevicePixels="True">
    <ContentPresenter
     HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
     VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
     SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
     ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
     ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
     Content="{TemplateBinding ContentControl.Content}" />
  </Border>
</ControlTemplate>