Controls
ItemsPresenter
ItemsPresenter is the template-level host for an ItemsControl's realized item containers. It does not generate items, choose templates, or own a collection by itself. Its job is to expose the owning control's existing item visuals and arrange them as one vertical stack.
Quick start
Use ItemsPresenter inside a ControlTemplate when you want the repeated item visuals from an ItemsControl, ListBox, TreeView, or another derived items control to appear at a specific spot in the template.
Minimal items host in a template
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<ItemsPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Framed item list
<Style x:Key="FeedStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="#101822"
BorderBrush="#2D465E"
BorderThickness="1"
Padding="12">
<ItemsPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Items host inside a scroll viewer
<Style x:Key="ScrollableItemsControlStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<ScrollViewer Padding="8">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Default mental model: ItemsPresenter is a placement marker for item visuals that already belong to an items control. Think "render the owner's realized items here," not "this is a standalone repeater."
What it does and what it does not do
What it does
Finds an owning ItemsControl, attaches to that owner as the active item host, and exposes the owner's realized item containers as its own visual and logical children.
What it does not do
It does not create containers, evaluate ItemTemplate, manage ItemsSource, support an ItemsPanel property, or introduce a custom layout algorithm.
- The owning
ItemsControlstill decides which item containers exist. - The presenter only changes where those realized containers are parented and measured.
- If no owner is found, the presenter has no children and reports a desired size of zero.
- When an owner is found, that owner reparents realized item containers under the presenter.
Owner discovery
ItemsPresenter locates its owner by walking up the logical or visual tree until it finds the nearest ancestor ItemsControl. That makes it a natural fit inside control templates, where the presenter lives somewhere beneath the templated items control.
Typical template relationship
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="#16212D"
BorderBrush="#34506C"
BorderThickness="1"
Padding="10">
<ItemsPresenter />
</Border>
</ControlTemplate>
In that arrangement, the presenter finds the surrounding ItemsControl, calls into it as the active host, and the owner moves its realized item containers under the presenter.
Practical rule: place ItemsPresenter under the items control whose items you want to show. If you move it outside that ownership chain, it will not find the correct source of realized items.
Layout behavior
The layout contract is fixed and intentionally simple. This implementation always measures and arranges realized item containers as a vertical stack.
Measure
Every realized container is measured using the same available size. The presenter's desired width becomes the maximum child width, and its desired height becomes the sum of child heights.
Arrange
Children are arranged top to bottom in realization order. Each child gets the full final width of the presenter and keeps its own measured height.
- Desired width = maximum realized item desired width.
- Desired height = sum of realized item desired heights.
- Each arranged child gets
finalSize.Xas its width. - The first child starts at the presenter's top edge; later children are placed immediately below the previous one.
<ItemsControl ItemsSource="{Binding Logs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#172331"
BorderBrush="#2B4259"
BorderThickness="1"
Padding="10"
Margin="0,0,0,8">
<TextBlock Text="{Binding Message}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Those generated item visuals remain vertically stacked whether the hosting template uses the presenter's default position directly or wraps it in other containers such as Border or ScrollViewer.
No ItemsPanel abstraction
WPF developers often expect ItemsPresenter to hand off layout to an ItemsPanel. That is not how this framework currently works. The presenter itself performs the vertical stacking behavior.
Supported expectation
Use the presenter to decide where repeated visuals appear inside a template.
Unsupported expectation
Do not expect swapping in a panel type such as WrapPanel or UniformGrid through an ItemsPanel property.
Framework-specific behavior: collection layout is vertically stacked by the owner or by ItemsPresenter. If you need a different collection layout contract, that requires a different control implementation rather than a presenter setting.
How it interacts with item generation
ItemsPresenter works with already realized item containers from the owning items control. That means templating, fallback container creation, grouping, and item container styling are still controlled by the owner.
Templates
ItemTemplate and ItemTemplateSelector are resolved by the owning ItemsControl before the presenter lays anything out.
Fallback containers
If the owner creates generated Label containers for plain data, those labels are what the presenter hosts.
Grouping
If the owner projects grouped visuals through GroupItem containers, the presenter hosts those group containers instead of the raw item containers.
Template-driven list with generated item visuals
<Style x:Key="NotificationsStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="#0F1822"
BorderBrush="#2F475F"
BorderThickness="1"
Padding="12">
<ItemsPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ItemsControl Style="{StaticResource NotificationsStyle}"
ItemsSource="{Binding Notifications}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#172331"
BorderBrush="#35516B"
BorderThickness="1"
Padding="10"
Margin="0,0,0,8">
<StackPanel>
<TextBlock Text="{Binding Title}" Margin="0,0,0,4" />
<TextBlock Text="{Binding Message}" />
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Property surface
ItemsPresenter does not add new public dependency properties of its own. You mainly work with it through placement and inherited FrameworkElement properties.
Inherited layout properties
Properties such as Width, Height, Margin, HorizontalAlignment, and VerticalAlignment affect the presenter's own slot like any other framework element.
No presenter-specific knobs
There is no public ItemsPanel, spacing, orientation, or container-generation property on this type.
Most customization happens around the presenter rather than on it. Typical examples include wrapping it in a Border, placing it in a ScrollViewer, or changing the owner's ItemTemplate.
Patterns and examples
Minimal template placeholder
<ControlTemplate TargetType="{x:Type ListBox}">
<ItemsPresenter />
</ControlTemplate>
Scrollable list shell
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="#111922"
BorderBrush="#35516B"
BorderThickness="1">
<ScrollViewer Padding="10">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
Grouped view with a custom shell
<ItemsControl ItemsSource="{StaticResource TasksView}">
<ItemsControl.GroupStyle>
<GroupStyle HeaderStringFormat="{0}" />
</ItemsControl.GroupStyle>
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="#121B25"
BorderBrush="#32485F"
BorderThickness="1"
Padding="12">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
ListBox chrome with the same item host contract
<Style x:Key="CompactListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border Background="#0F1720"
BorderBrush="#2D465E"
BorderThickness="1"
Padding="6">
<ItemsPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notes and pitfalls
Do not treat it as a standalone control. Placing an ItemsPresenter in arbitrary XAML without an owning ItemsControl above it gives you an empty host.
One presenter usually means one active host. The owning items control attaches to the active items host, so templates should provide a single clear location where realized items belong.
Layout is always vertical here. If you expected wrapping, horizontal flow, or grid-style item placement, this implementation does not expose that through ItemsPresenter.
No virtualization guarantee. The presenter hosts the owner's realized visuals, and those realized children are still measured and arranged in order.