33

Adding more than one child to a WPF StatusBar results in poor layout with little option to customize. For example, this code:

<Window x:Class="StatusBar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <StatusBar DockPanel.Dock="Bottom">
            <StatusBarItem>
                <TextBlock>Ready</TextBlock>
            </StatusBarItem>
            <StatusBarItem>
                <TextBlock>Set</TextBlock>
            </StatusBarItem>
        </StatusBar>

        <Label>Main Content</Label>
    </DockPanel>
</Window>

Results in:

enter image description here

This is not the ideal layout, since the "Set" is squeezed right up against the "Ready".

How do I gain full control over the layout of the WPF StatusBar control?

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393

4 Answers4

88

By default, the StatusBar uses a DockPanel to position its children. This works fine for one item, but tends to make things messy and inconvenient when working with more than one child.

To gain a high level of control over the positioning of status bar children, you can swap out the DockPanel for a Grid:

<Window x:Class="StatusBar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <StatusBar DockPanel.Dock="Bottom">
            <StatusBar.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="4*"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </StatusBar.ItemsPanel>
            <StatusBarItem>
                <TextBlock>Ready</TextBlock>
            </StatusBarItem>
            <StatusBarItem Grid.Column="1">
                <ProgressBar Value="30" Width="80" Height="18"/>
            </StatusBarItem>
            <StatusBarItem Grid.Column="2">
                <TextBlock>Set</TextBlock>
            </StatusBarItem>
            <StatusBarItem Grid.Column="3">
                <TextBlock>Go!</TextBlock>
            </StatusBarItem>
        </StatusBar>

        <Label>Main Content</Label>
    </DockPanel>
</Window>

This results in:

enter image description here

For a more in-depth discussion, please visit my blog post here.

CAD bloke
  • 8,578
  • 7
  • 65
  • 114
Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 40
    @David: don't be ridiculous. I posted this question because google analytics told me that was one of my most popular blog posts, so having a direct answer to this question on stackoverflow would be beneficial to the community. I have no adverts on my blog so don't stand to gain anything from link baiting. And I put more than enough information in my answer that you don't even need to visit my blog unless you want more info. Now kindly go and find something constructive to do. – Kent Boogaart Dec 07 '10 at 22:58
  • Mmmm, someone knows why if I put a separator inside a StatusBarItem it does not gets painted? Thanks. – Ignacio Soler Garcia Sep 29 '11 at 06:57
  • Broken link needed to be fixed. – ΩmegaMan Jun 13 '15 at 16:27
  • Your blog is like my blog; no ads and a clean interface, that speaks volumes. :-) – ΩmegaMan Jun 14 '15 at 12:20
  • Is there a way to make the progressbar stretch vertically without using a hard-coded height value? – AntikM Aug 13 '20 at 16:07
12

Actually, following Kent's reply I tried this and it works fine:

<StatusBar>
    <StatusBarItem DockPanel.Dock="Right">
        <TextBlock>Go!</TextBlock>
    </StatusBarItem>
    <StatusBarItem DockPanel.Dock="Right">
        <TextBlock>Set</TextBlock>
    </StatusBarItem>
    <StatusBarItem DockPanel.Dock="Right">
        <ProgressBar Value="30" Width="80" Height="18"/>
    </StatusBarItem>
    <!-- Fill last child is true by default -->
    <StatusBarItem>
        <TextBlock>Ready</TextBlock>
    </StatusBarItem>
</StatusBar>
Afshin
  • 530
  • 5
  • 8
  • 1
    I didn't suggest it wouldn't work, but that it's "messy and inconvenient" because it's in an illogical order, and because you have far less control over the layout. Try making the *Set* item take up half the available width and you'll see what I mean. – Kent Boogaart May 26 '10 at 07:03
  • 6
    I think that if you understand how a DockPanel works, this is the cleanest way to do it. – Sonhja Jul 15 '13 at 09:28
  • 1
    doesn't seem to work if my statusbar is in a usercontrol and that usercontrol is being shown as a contentcontrol where the contentcontrol is docked to the bottom. – juFo Oct 02 '17 at 13:06
2

Just for the sake of reference for those reading the excellent answers above I'd like to suggest something even more simpler that achieves the same results. (Using neither DockPanel nor StatusBar).

<Window>
.
.

 <Grid Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="15"/>
        </Grid.RowDefinitions>

        <SomeContainer Grid.Row="0" />  <!-- Main Content.. -->

        <Grid Grid.Row="1">
             <!-- Status bar laid out here (using similar approach)-->
        </Grid>
</Window>

Disclaimer : This was long ago at a time when I was starting out with WPF.

Robin Maben
  • 22,194
  • 16
  • 64
  • 99
0

You can use a container like StackPanel to move a group of status bar items to the right

<StatusBarItem>
    <Button Content="Left Aligned Button"/>
</StatusBarItem>
<StatusBarItem HorizontalAlignment="Right">
    <StackPanel Orientation="Horizontal">
        <StatusBarItem>
            <Button Content="Right Aligned Button 1"/>
        </StatusBarItem>
        <StatusBarItem >
            <Button Content="Right Aligned Button 2"/>
        </StatusBarItem>
    </StackPanel>
</StatusBarItem>
Pavel Popov
  • 111
  • 1
  • 3