WPF Standard Control Demo App › Expander
Expander Display
Expander shows a header at all times and shows or hides its content when the header is clicked.
What collapsed content costs
Expander derives from HeaderedContentControl. Its Content is what is shown and hidden, and collapsed content costs less than it may seem. In an Expander collapsed from the start, the content element was created and received Loaded, but it was not measured. A ListBox of 1000 items inside it created no ListBoxItem at all: in this setup, the list created and measured no item containers until the Expander was expanded, although the content element itself was created and loaded. After expanding, the content was measured, the ListBox created 11 items, and Loaded was raised on the content a second time. Do not start heavy work in the content’s Loaded handler: it runs while the Expander is collapsed, and again when it is expanded.
Expanding and collapsing, with no animation
IsExpanded decides whether the content is shown; the default is False. It binds two-way by default, so a view model property bound to it follows the user’s clicks. The demo app binds it to a check box without a Mode, so the two stay in step. A click on the header with the real mouse expanded the Expander, checked the box, and raised Expanded. Clearing the box collapsed it and raised Collapsed.
The header in the default template is a ToggleButton named HeaderSite. The template has no visual state groups and no animation: it switches with triggers on IsExpanded, ExpandDirection, and IsEnabled. When IsExpanded was set to False, the content was Collapsed at once. To animate, use a template of your own.
| case | measured |
|---|---|
| base class / IsExpanded default, two-way by default / ExpandDirection | HeaderedContentControl / False, True / Down |
| default template: header element / VisualStateGroups | ToggleButton named HeaderSite / 0 |
| triggers | IsExpanded=True; ExpandDirection=Right, Up, Left; IsEnabled=False |
| IsExpanded set to False: content Visibility at once / after 50 ms | Collapsed / Collapsed |
| real mouse click on header: IsExpanded / bound CheckBox / events | True / True / Expanded |
| then the CheckBox cleared: IsExpanded / events | False / Collapsed |
| collapsed: child Loaded / measured / items in a 1000-item ListBox | 1 / 0 / 0 |
| after expanding | 2 / 1 / 11 |
The template, clicks, and collapsed content. Measured on .NET 10 / Windows 11.
Where the header and the content go
ExpandDirection decides where the content appears relative to the header; the default is Down. With a content 80 × 40, Down placed the header on top and the content below it, and Up placed the content above the header. With Left and Right, the header became a column beside the content, 49 wide and 39 high, with its text still horizontal in the lower part of the column. The content was on the left for Left and on the right for Right.
HasHeader is read-only and tells whether there is a Header. With Header null, HasHeader was False, but the header’s ToggleButton, with its arrow, stayed visible, 19 high. Hiding it takes a template of your own.
Properties that reach the header as well as the content
The Control properties set on the Expander apply to the header too, not only to the content.
Padding: withPadding="20", the header grew from 19 to 59 high, and the content moved down with it.- Font properties:
FontWeight="Bold"set on the Expander made both the header’s text and a TextBlock in the content bold. Foreground: withRed, the text of both the header and the content was red.Background: it is painted behind both the header and the content. With a 200-wide Expander, the painted area was 200 × 38.96 and contained the header and the content.Backgrounditself is not an inherited property, so it is the area behind the content that is colored. Set it on the Expander to color the header and the content together.BorderBrush/BorderThickness: a border around the whole Expander, header included. Measured on its own, withoutPadding,BorderThickness="5"moved the header in by 5 from each edge, from (1, 1) to (6, 6), and the content down by 5.
| case | measured |
|---|---|
| ExpandDirection=Down: header / content / header text | x=2 y=2 w=116 h=19 / x=20 y=22 w=80 h=40 / x=25 y=3.52 w=49.04 h=15.96 |
| ExpandDirection=Up: header / content / header text | x=2 y=42 w=116 h=19 / x=20 y=1 w=80 h=40 / x=25 y=43.52 w=49.04 h=15.96 |
| ExpandDirection=Left: header / content / header text | x=82 y=2 w=49.04 h=38.96 / x=1 y=1.48 w=80 h=40 / x=82 y=25 w=49.04 h=15.96 |
| ExpandDirection=Right: header / content / header text | x=2 y=2 w=49.04 h=38.96 / x=52.04 y=1.48 w=80 h=40 / x=2 y=25 w=49.04 h=15.96 |
| Header=null: HasHeader / header ToggleButton Visibility, size | False / Visible, 196 x 19 |
| FontWeight=Bold, Foreground=Red: header text / content text | Bold, #FFFF0000 / Bold, #FFFF0000 |
| Background: painted area / header / content (inside it) | x=0 y=0 w=200 h=38.96 / x=2 y=2 w=196 h=19 / x=1 y=22 w=198 h=15.96 (True) |
| Padding=0, BorderThickness=0: header / content | x=1 y=1 w=198 h=19 / x=60 y=21 w=80 h=40 |
| Padding=20, BorderThickness=0: header / content | x=1 y=1 w=198 h=59 / x=60 y=81 w=80 h=40 |
| Padding=0, BorderThickness=5: header / content | x=6 y=6 w=188 h=19 / x=60 y=26 w=80 h=40 |
ExpandDirection, the header, and the Control properties. Measured on .NET 10 / Windows 11.
Trying it in the demo app

The Expander page of the demo app has sections for ExpandDirection, IsExpanded, the header, the content, and the Control properties Padding, the font properties, Background, Foreground, and the border. The header section turns an empty text box into null. The “Show Code” link under each section displays its XAML. The following XAML is the IsExpanded section (ExpanderUsageControl.xaml), with the styles and the surrounding GroupBoxes left out and the namespace declarations added:
<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<CheckBox x:Name="IsExpandedCheckBox" VerticalContentAlignment="Center" Content="IsExpanded" />
<Expander x:Name="IsExpandedExpander"
Content="CONTENT"
Header="Expander"
IsExpanded="{Binding IsChecked, ElementName=IsExpandedCheckBox}" />
</StackPanel>
Related controls and articles
- GroupBox — a header and a border around content that is always shown.
- ToggleButton — the element the header is made of.
- TreeView — folding for a hierarchy of items rather than a few sections.
Source code and how it was measured
Every behavior on this page was measured by running it on .NET 10 / Windows 11, using ExpanderDemoScene in this site’s screenshot tool. The click on the header was made with the real mouse over the measuring window. Positions are measured from the Expander’s top-left corner, and sizes are the values on the measuring machine.