如何自定义WPF StatusBar的布局?

33

在 WPF 中向 StatusBar 添加多个子元素会导致布局不佳,并且很难进行自定义。例如,以下代码:

<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>

结果如下:

enter image description here

这不是理想的布局,因为“Set”紧贴着“Ready”。

我如何完全控制 WPF StatusBar 控件的布局?

4个回答

88

默认情况下,StatusBar使用DockPanel来定位其子元素。当只有一个子项时,这样做是有效的,但是在处理多个子项时会变得混乱和不方便。

为了对状态栏子元素的位置获得高度控制,您可以将DockPanel替换为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>

这将导致:

在此输入图片描述

欲了解更深入的讨论,请参阅我的博客文章此处


40
@David:别胡扯了。我发这个问题是因为谷歌分析告诉我这是我最受欢迎的博客文章之一,所以在stackoverflow上直接回答这个问题对社区有益。我的博客上没有广告,所以我不会从链接诱饵中获得任何好处。我在我的回答中提供了足够的信息,除非你想要更多的信息,否则你甚至不需要访问我的博客。现在请你去找一些有益的事情做。 - Kent Boogaart
有人知道为什么如果我在 StatusBarItem 中放置一个分隔符,它就不会被绘制吗?谢谢。 - Ignacio Soler Garcia
需要修复损坏的链接。 - ΩmegaMan
你的博客就像我的博客一样,没有广告和简洁的界面,这说明了很多。 :-) - ΩmegaMan
有没有一种方法可以使进度条在不使用硬编码高度值的情况下垂直拉伸? - antikbd

12

实际上,遵循 Kent 的回答,我尝试了这个方法,它很好地工作:

<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>

1
我并没有说它不会起作用,但是因为它的顺序不合逻辑,而且你对布局的控制力要少得多,所以它显得“混乱和不方便”。试着让“Set”项目占据可用宽度的一半,你就会明白我的意思了。 - Kent Boogaart
6
我认为如果您了解DockPanel的工作原理,这是最简洁的方法。 - Sonhja
1
如果我的状态栏位于用户控件中,并且该用户控件作为内容控件显示在底部停靠的位置,则似乎无法正常工作。 - juFo

2

为了参考上面优秀答案的读者,我想提供更简单的方法来实现相同的结果(不使用DockPanelStatusBar)。

<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>

免责声明:此文是在我刚开始学习WPF时所写,现在已经很久了。


为什么需要免责声明?今天为什么有人不这样做? - Jazz.

0
您可以使用 StackPanel 这样的容器将一组状态栏项目向右移动。
<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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接