目录

WPF-ToolBarTray,ToolBar,StatusBar

Windows Presentation Foundation中,ToolBarTray、ToolBar、StatusBar是典型的"命令承载与状态反馈"UI结构组件。

一、ToolBarTray

ToolBarTrayToolBar 的容器管理器,用于:

  • 承载多个 ToolBar

  • 支持 ToolBar 分组排列(行 / 列)

  • 支持拖拽重排(Band / BandIndex)

  • 支持 ToolBar 停靠行为

ToolBarTray = “可编排工具栏宿主”

核心属性:

属性 作用
Orientation 工具栏排列方向
IsLocked 是否禁止拖动
Background 背景
ToolBars 子工具栏集合

ToolBar 上的重要属性:

属性 作用
Band 所在行
BandIndex 行内顺序
Header 标题
OverflowMode 溢出策略

使用场景:

  • CAD 系统
  • 报表设计器
  • 编辑器(文本,图片,流程)
  • 企业后台复杂管理系统

**适合:**功能多,操作频繁,需要分组命令

**不适合:**简单的CRUD页面,简单的CRUD页面使用Ribbon或普通按钮更便利一点。

二、ToolBar

ToolBar是命令按钮的承载容器。

支持放置:

  • Button
  • ToggleButton
  • ComboBox
  • TextBox
  • Separator
  • 自定义控件

内部自带:

  • 溢出面板
  • 键盘导航
  • 样式支持

适合场景:

  • 命令高频
  • 命令具有明显分组
  • 适合放图标性操作

不适合放复杂表单

三、StatusBar

StatusBar 用于:展示系统当前状态 / 反馈信息

常见内容:

  • 当前用户
  • 服务器状态
  • 选中对象信息
  • 鼠标坐标
  • 进度条
  • 日志提示

使用场景:

  • 文本编辑器(字数统计)
  • 图像软件(分辨率)
  • ERP系统(连接状态)
  • 数据采集系统(实时数值)

三者的协作模式

标准布局结构:

DockPanel
 ├── ToolBarTray (Top)
 ├── 主内容区域
 └── StatusBar (Bottom)

形成:

  • 命令输入(ToolBar)
  • 业务处理(Content)
  • 状态反馈(StatusBar)

深入使用场景

  1. ToolBarTray & ToolBar: 如果你只需要一行固定的按钮,直接用 ToolBar。但如果你想模仿 Office 或 Visual Studio 那种可拖拽、多行排列的界面,必须使用 ToolBarTray。它能自动处理子级 ToolBar 的换行(Band 属性)和溢出处理。
  2. StatusBar: 它是应用与用户的“悄悄话”窗口。不要在状态栏放核心业务按钮,它应该保持低干扰性

示例:

<Window
    x:Class="demo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:demo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">

    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>

    <DockPanel>
        <!--  1. ToolBarTray 区域  -->
        <ToolBarTray Background="GhostWhite" DockPanel.Dock="Top">
            <!--  第一个工具栏 (Band 0)  -->
            <ToolBar Band="0" BandIndex="0">
                <Button Command="{Binding SaveCommand}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Margin="0,0,5,0" Text="💾" />
                        <TextBlock Text="保存" />
                    </StackPanel>
                </Button>
                <Separator />
                <Button Content="新建" />
                <Button Content="打开" />
            </ToolBar>

            <!--  第二个工具栏 (Band 0,会接在后面或另起一行)  -->
            <ToolBar Band="0" BandIndex="1">
                <ComboBox Width="120" SelectedIndex="0">
                    <ComboBoxItem Content="微软雅黑" />
                    <ComboBoxItem Content="Consolas" />
                </ComboBox>
                <ToggleButton
                    Width="30"
                    Content="B"
                    FontWeight="Bold" />
                <ToggleButton
                    Width="30"
                    Content="I"
                    FontStyle="Italic" />
            </ToolBar>
        </ToolBarTray>

        <!--  2. StatusBar 区域  -->
        <StatusBar Background="#F0F0F0" DockPanel.Dock="Bottom">
            <StatusBarItem>
                <TextBlock Text="{Binding StatusMessage}" />
            </StatusBarItem>
            <Separator />
            <StatusBarItem>
                <ProgressBar
                    Width="100"
                    Height="15"
                    Value="{Binding ProgressValue}" />
            </StatusBarItem>
            <StatusBarItem HorizontalAlignment="Right">
                <TextBlock Margin="0,0,10,0" Text="UTF-8" />
            </StatusBarItem>
        </StatusBar>

        <!--  3. 主内容区域  -->
        <Grid>
            <TextBox
                Padding="10"
                AcceptsReturn="True"
                Text="在工具栏点击保存或处理,观察状态栏变化。你可以尝试拖动工具栏左侧的把手来移动它。" />
            <Button
                Margin="20"
                Padding="10,5"
                HorizontalAlignment="Right"
                VerticalAlignment="Bottom"
                Command="{Binding ProcessCommand}"
                Content="开始后台处理" />
        </Grid>
    </DockPanel>
</Window>
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace demo
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private string _statusMessage = "就绪";
        private int _progressValue = 0;

        public string StatusMessage
        {
            get => _statusMessage;
            set { _statusMessage = value; OnPropertyChanged(); }
        }

        public int ProgressValue
        {
            get => _progressValue;
            set { _progressValue = value; OnPropertyChanged(); }
        }

        // 命令定义
        public ICommand SaveCommand { get; }
        public ICommand ProcessCommand { get; }

        public MainViewModel()
        {
            SaveCommand = new RelayCommand(_ => StatusMessage = $"文件已于 {DateTime.Now:T} 保存");
            ProcessCommand = new RelayCommand(_ => SimulateWork());
        }

        private async void SimulateWork()
        {
            StatusMessage = "正在处理数据...";
            for (int i = 0; i <= 100; i += 10)
            {
                ProgressValue = i;
                await System.Threading.Tasks.Task.Delay(200);
            }
            StatusMessage = "处理完成!";
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}