WPF Bootcamp

Controls and Content Model

WPF controls are not all the same kind of thing. Some host one piece of content, some host a collection, some generate containers, and some mostly exist to present content defined elsewhere.

If you understand the content model, you stop forcing controls into jobs they were not designed to do, and the whole control library becomes easier to navigate.

What you'll learn

  • The difference between a content control, items control, headered control, and presenter.
  • Why some controls accept a single child while others render arbitrary collections.
  • How generated containers affect styling, selection, and templates.
  • How to choose the right control family based on what kind of content relationship you need.

ContentControl

Button, ContentControl, and similar types host one logical piece of content, which can itself be a complex tree.

ItemsControl

ListBox, ComboBox, and TreeView repeat visuals for a collection and often wrap each item in a generated container.

The mental model in one sentence

A control's content model defines what kind of thing it is responsible for hosting: one object, one object plus a header, many items, or a placeholder where templated content gets injected.

One main thing

Content controls host one logical content object, even if that object is itself a small subtree.

Many repeated things

Items controls host collections and generate a visual representation per item.

Template insertion point

Presenters are the bridge between a control's public API and the visuals created by its template.

Content controls: one logical content value

A content control has one primary content property. That content can be a string, a number, a model object, or an entire tree of elements. The important part is that the control conceptually hosts one main piece of content.

<Button>
    <StackPanel Orientation="Horizontal">
        <Path Data="..." />
        <TextBlock Text="Save" Margin="8,0,0,0" />
    </StackPanel>
</Button>

That still counts as a single content value. The content just happens to be a panel containing multiple children.

Examples

Button, Label, ContentControl, Window, and often UserControl all fit the "one main content object" model.

Why it matters

If a control is a content control, you do not add multiple sibling children directly. You give it one content object, and that object can be a container if needed.

Headered controls: identity plus content

Some controls conceptually host both a header-like label and another content value. This is common for controls that need a caption or title in addition to their main content.

<GroupBox Header="Profile">
    <StackPanel>
        <TextBlock Text="Name" />
        <TextBox />
    </StackPanel>
</GroupBox>

Here the header is not the same thing as the main content. The control model exposes both concepts separately, and the template decides where each one gets rendered.

This distinction also shows up in controls like TabItem, Expander, and menu-related elements where a header or title matters independently from the body content.

Items controls: collections, not hand-written repetition

An items control is for displaying many things from a collection. Instead of manually writing repeated children, you give the control items and let it generate visuals for each one.

<ListBox ItemsSource="{Binding Orders}" />

That one line means something fundamentally different from a panel full of repeated child tags. The ListBox owns item generation, selection state, keyboard navigation, and often scrolling behavior.

Practical takeaway: if the UI is showing a collection of data, reach for an ItemsControl family member before you start manually adding repeated visuals to a panel.

Item data is not the same as item containers

One of the most important ideas in WPF is that the data item and the generated UI container are different objects.

<ListBox ItemsSource="{Binding Orders}" />

If Orders contains business objects, the items control does not just place those objects directly on screen. It typically wraps each item in a container like ListBoxItem, then uses templates or default rendering rules to present the item.

Data item

Your model or view model object, such as an OrderViewModel.

Container

The control-generated wrapper, such as ListBoxItem or ComboBoxItem, which carries selection, focus, and other control-specific behavior.

This distinction matters for styling, selection, triggers, and debugging. If you do not know whether you are editing the item template or the container style, you will often change the wrong thing.

Panels are containers, not items controls

A panel like StackPanel or Grid lays out children that you explicitly place inside it. It does not generate visuals from data items, and it does not provide items-control behavior like selection or item containers.

<StackPanel>
    <TextBlock Text="Order A" />
    <TextBlock Text="Order B" />
</StackPanel>

This is appropriate when the child set is small and explicit. It is not the right abstraction for a dynamic list of data coming from a collection.

Presenters explain the magic

A ContentPresenter or ItemsPresenter inside a template is how the template says, "put the user-provided content here." That is the bridge between the control API and the visuals defined by its template.

<ControlTemplate TargetType="Button">
    <Border Padding="12,8">
        <ContentPresenter />
    </Border>
</ControlTemplate>

The template defines the border and chrome. The presenter marks the location where the button's content should appear. Without that presenter, the control might still exist, but user-provided content would have nowhere to render.

Data templates decide how data becomes visuals

For items controls and other content scenarios, a data template defines how a data object should be presented.

<ListBox ItemsSource="{Binding Orders}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding CustomerName}" />
                <TextBlock Text="{Binding Total}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

The items control still owns the collection behavior and container generation. The data template only decides what each item's inner visual content looks like.

Choosing the right abstraction

Use a content control when

You have one main thing to host, even if that one thing is a composite visual tree.

Use a headered control when

You need a title or label concept that is distinct from the main body content.

Use an items control when

You are presenting a collection and want the control to own repetition, containers, and interaction behavior.

Use a panel when

You are manually composing a fixed set of child elements and only need layout behavior.

A worked example

Compare these two snippets:

<StackPanel>
    <TextBlock Text="Order A" />
    <TextBlock Text="Order B" />
</StackPanel>

<ListBox ItemsSource="{Binding Orders}" />

They may both result in multiple rows on screen, but they represent different mental models.

  1. The StackPanel version is explicit composition. You authored each child yourself.
  2. The ListBox version is data-driven composition. The control generates visuals from a collection.
  3. The ListBox can provide selection, focus behavior, keyboard navigation, scrolling, and container state out of the box.
  4. The StackPanel gives you none of that because it is only a layout panel.

That difference is the heart of the content model: not all "things that contain children" are responsible for the same kind of containment.

Common mistakes

  • Using a StackPanel where an ItemsControl should own repetition and item generation.
  • Confusing item data with item containers such as ListBoxItem.
  • Editing a control template without understanding where its presenter is supposed to sit.
  • Forgetting that a content control can host only one logical content value, even if that value is a whole layout subtree.
  • Styling the data template when the real issue is container behavior, or styling the container when the issue is item content.

InkkSlinger parity note: The same distinction matters in this repo. Controls like ItemsControl, ListBox, ComboBox, and TreeView carry WPF-style item generation concepts, while content controls host one main child or content object.

Next, go deeper into dependency properties, because the content model only works cleanly because WPF has a richer property system than normal CLR properties.