当前位置: 首页 > news >正文

003011001_WPF布局实例

003011001_WPF 布局实例

摘要:本文面向 WPF 开发者,系统梳理从入门到工业级的四大布局实战案例——设备登录界面(Grid + StackPanel)、设备列表界面(DockPanel + 数据绑定)、工业设备操作面板(Canvas + 动态交互)以及生产监控主界面(虚拟化 + 多区域布局)。每个实例均包含 XAML 代码、后台 C# 代码及关键知识点解析,并深入讲解 VirtualizingStackPanel 的 UI 虚拟化与容器回收原理,帮助读者循序渐进掌握 WPF 布局核心技能与性能优化技巧。

难度等级:⭐ 入门级(基础布局组合)

实例 1:设备登录界面

学习目标:掌握Grid行列划分、StackPanel垂直/水平排列、Border装饰器的基础用法。

功能:包含用户名输入、密码输入、登录/取消按钮,居中布局。

XAML:

<Window x:Class="WpfLayoutDemo.LoginWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="设备登录" Width="400" Height="300" WindowStartupLocation="CenterScreen" ResizeMode="NoResize"> <!-- 外层Border:添加圆角和阴影 --> <Border Background="#F5F5F5" CornerRadius="10" Margin="10"> <!-- 3行1列Grid:划分标题区、输入区、按钮区 --> <Grid Margin="20"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- 1. 标题区 --> <TextBlock Grid.Row="0" Text="工业设备管理系统" FontSize="22" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,20"/> <!-- 2. 输入区:垂直StackPanel --> <StackPanel Grid.Row="1"> <!-- 用户名行:水平StackPanel --> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <TextBlock Text="用户名:" Width="60" FontSize="14"/> <TextBox Width="200" Height="30" FontSize="14"/> </StackPanel> <!-- 密码行 --> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <TextBlock Text="密 码:" Width="60" FontSize="14"/> <PasswordBox Width="200" Height="30" FontSize="14"/> </StackPanel> </StackPanel> <!-- 3. 按钮区:水平StackPanel,右对齐 --> <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,20,0,0"> <Button Content="登录" Width="80" Height="35" Background="#2196F3" Foreground="White"/> <Button Content="取消" Width="80" Height="35"/> </StackPanel> </Grid> </Border> </Window>

关键知识点

  • Grid.RowDefinitions定义行高,Auto= 自适应内容,*= 占满剩余空间
  • StackPanel.Orientation控制排列方向(垂直/水平)
  • Border为整个窗口添加圆角和背景,提升视觉效果

难度等级:⭐⭐ 进阶级(嵌套布局 + 数据绑定)

实例 2:设备列表界面

学习目标:掌握DockPanel停靠布局、ListView数据绑定、DataTemplate自定义列表项、嵌套Grid布局。

功能:包含顶部标题栏、左侧设备分类、右侧设备列表,列表项显示设备 ID、状态、运行时间。

XAML:

<Window x:Class="WpfLayoutDemo.DeviceListWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="设备列表" Width="800" Height="600"> <!-- DockPanel:顶部停靠标题栏,左侧停靠分类栏,剩余空间给列表 --> <DockPanel> <!-- 1. 顶部标题栏(停靠顶部) --> <Border DockPanel.Dock="Top" Background="#2196F3" Height="50"> <TextBlock Text="设备管理系统" FontSize="18" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <!-- 2. 左侧分类栏(停靠左侧) --> <Border DockPanel.Dock="Left" Background="#F0F0F0" Width="150" Margin="0,0,1,0"> <StackPanel Margin="10"> <Button Content="全部设备" Height="35" Background="#E3F2FD"/> <Button Content="CNC设备" Height="35"/> <Button Content="AOI设备" Height="35"/> <Button Content="输送线" Height="35"/> </StackPanel> </Border> <!-- 3. 右侧设备列表(占满剩余空间) --> <ListView x:Name="DeviceListView" Margin="10"> <ListView.ItemTemplate> <DataTemplate> <!-- 列表项:嵌套Grid布局 --> <Border BorderBrush="#E0E0E0" BorderThickness="1" CornerRadius="5" Padding="10" Margin="0,5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <!-- 状态指示灯 --> <Ellipse Grid.Column="0" Width="15" Height="15" Fill="{Binding StatusColor}" Margin="0,0,10,0"/> <!-- 设备信息 --> <StackPanel Grid.Column="1"> <TextBlock Text="{Binding DeviceId}" FontSize="14" FontWeight="Bold"/> <TextBlock Text="{Binding DeviceName}" FontSize="12" Foreground="Gray"/> </StackPanel> <!-- 运行时间 --> <TextBlock Grid.Column="2" Text="{Binding RunTime}" FontSize="12" VerticalAlignment="Center"/> </Grid> </Border> </DataTemplate> </ListView.ItemTemplate> </ListView> </DockPanel> </Window>

后台绑定代码

C#:

public partial class DeviceListWindow : Window { public class DeviceInfo { public string DeviceId { get; set; } public string DeviceName { get; set; } public SolidColorBrush StatusColor { get; set; } public string RunTime { get; set; } } public DeviceListWindow() { InitializeComponent(); LoadDeviceData(); } private void LoadDeviceData() { var devices = new List<DeviceInfo> { new DeviceInfo { DeviceId = "CNC_001", DeviceName = "数控车床1号", StatusColor = Brushes.Green, RunTime = "123小时" }, new DeviceInfo { DeviceId = "AOI_002", DeviceName = "光学检测2号", StatusColor = Brushes.Red, RunTime = "89小时" }, new DeviceInfo { DeviceId = "CNC_003", DeviceName = "数控车床3号", StatusColor = Brushes.Yellow, RunTime = "256小时" } }; DeviceListView.ItemsSource = devices; } }

关键知识点

  • DockPanel.Dock控制子元素停靠位置(Top/Left/Right/Bottom)
  • DataTemplate自定义列表项的外观
  • 简单数据绑定:将后台集合绑定到ListView.ItemsSource

难度等级:⭐⭐⭐ 高级(Canvas 绝对布局 + 动态交互)

实例 3:工业设备操作面板

学习目标:掌握Canvas绝对定位、ZIndex层级控制、动态修改控件属性、定时器实时更新。

功能:固定尺寸的设备操作面板,包含状态指示灯、实时数据显示、操作按钮,支持状态切换。

XAML:

<Window x:Class="T007003_WPFLayoutDemo.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:T007003_WPFLayoutDemo" mc:Ignorable="d" Title="设备操作面板" Width="800" Height="600" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"> <Canvas Width="800" Height="600" Background="#F0F0F0"> <!-- 1. 背景图(底层,ZIndex=0) --> <Rectangle Canvas.Left="0" Canvas.Top="0" Width="800" Height="600" Fill="#ECEFF1" /> <!-- 2. 状态指示灯区 --> <Border Canvas.Left="50" Canvas.Top="50" Width="300" Height="100" Background="White" CornerRadius="5" Padding="15"> <StackPanel Orientation="Horizontal" > <StackPanel > <Ellipse x:Name="RunStatusLight" Width="40" Height="40" Fill="Red" /> <TextBlock Text="运行状态" HorizontalAlignment="Center" /> </StackPanel> <StackPanel > <Ellipse x:Name="AlarmStatusLight" Width="40" Height="40" Fill="Gray" /> <TextBlock Text="报警状态" HorizontalAlignment="Center" /> </StackPanel> </StackPanel> </Border> <!-- 3. 实时数据区 --> <Border Canvas.Left="50" Canvas.Top="180" Width="300" Height="200" Background="White" CornerRadius="5" Padding="15"> <StackPanel> <TextBlock Text="实时数据" FontSize="16" FontWeight="Bold" /> <StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="当前温度:" Width="80" /> <TextBlock x:Name="TxtTemperature" Text="25.5℃" Foreground="Blue" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="当前转速:" Width="80" /> <TextBlock x:Name="TxtSpeed" Text="1500 rpm" Foreground="Blue" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="产量:" Width="80" /> <TextBlock x:Name="TxtOutput" Text="1234 件" Foreground="Blue" /> </StackPanel> </StackPanel> </StackPanel> </Border> <!-- 4. 操作按钮区 --> <Border Canvas.Left="50" Canvas.Top="410" Width="700" Height="120" Background="White" CornerRadius="5" Padding="15"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button x:Name="BtnStart" Content="启动" Width="120" Height="50" Background="Green" Foreground="White" FontSize="16" Click="BtnStart_Click" /> <Button x:Name="BtnStop" Content="停止" Width="120" Height="50" Background="Red" Foreground="White" FontSize="16" Click="BtnStop_Click" /> <Button x:Name="BtnReset" Content="复位" Width="120" Height="50" Background="Gray" Foreground="White" FontSize="16" Click="BtnReset_Click" /> <Button x:Name="BtnAlarm" Content="模拟报警" Width="120" Height="50" Background="Orange" Foreground="White" FontSize="16" Click="BtnAlarm_Click" /> </StackPanel> </Border> </Canvas> </Window>

后台交互代码

C#:

public partial class DevicePanelWindow : Window { private DispatcherTimer _timer; private Random _random = new Random(); public DevicePanelWindow() { InitializeComponent(); _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; _timer.Tick += Timer_Tick; _timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { // 模拟实时数据更新 TxtTemperature.Text = $"{25 + _random.NextDouble() * 10:F1}℃"; TxtSpeed.Text = $"{1500 + _random.Next(-100, 100)} rpm"; } private void BtnStart_Click(object sender, RoutedEventArgs e) { RunStatusLight.Fill = Brushes.Green; MessageBox.Show("设备已启动"); } private void BtnStop_Click(object sender, RoutedEventArgs e) { RunStatusLight.Fill = Brushes.Red; MessageBox.Show("设备已停止"); } private void BtnReset_Click(object sender, RoutedEventArgs e) { RunStatusLight.Fill = Brushes.Gray; AlarmStatusLight.Fill = Brushes.Gray; TxtOutput.Text = "0 件"; MessageBox.Show("设备已复位"); } private void BtnAlarm_Click(object sender, RoutedEventArgs e) { AlarmStatusLight.Fill = Brushes.Red; MessageBox.Show("模拟报警触发"); } }

关键知识点

  • Canvas.Left/Canvas.Top精确控制控件位置
  • DispatcherTimer实现 UI 线程的定时更新
  • 动态修改控件的FillText等属性实现状态切换

难度等级:⭐⭐⭐⭐ 工业级(虚拟化 + 多区域 + 性能优化)

实例 4:生产监控主界面

学习目标:掌握Grid复杂嵌套、VirtualizingStackPanel虚拟化、UniformGrid均匀布局、样式复用、多区域布局。

功能:完整的工业上位机主界面,包含顶部导航栏、左侧菜单、主内容区(4 个产能卡片 + 数据表格)、底部状态栏。

XAML:

<Window x:Class="WpfLayoutDemo.MonitorWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="生产监控系统" Width="1200" Height="800" WindowStartupLocation="CenterScreen"> <!-- 整体3行1列Grid:顶部导航、中间内容、底部状态栏 --> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> <RowDefinition Height="30"/> </Grid.RowDefinitions> <!-- 1. 顶部导航栏 --> <Border Grid.Row="0" Background="#1976D2"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="生产监控系统" FontSize="18" Foreground="White" VerticalAlignment="Center" Margin="20,0"/> <TextBlock Grid.Column="2" Text="当前用户:管理员" Foreground="White" VerticalAlignment="Center" Margin="0,0,20,0"/> </Grid> </Border> <!-- 2. 中间内容区:2列Grid(左侧菜单+右侧主内容) --> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="180"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- 左侧菜单 --> <Border Grid.Column="0" Background="#F5F5F5" BorderThickness="0,0,1,0" BorderBrush="#E0E0E0"> <StackPanel Margin="0,10" Spacing="2"> <Button Content="生产监控" Height="40" Background="#E3F2FD" HorizontalContentAlignment="Left" Padding="20,0"/> <Button Content="设备管理" Height="40" HorizontalContentAlignment="Left" Padding="20,0"/> <Button Content="产量统计" Height="40" HorizontalContentAlignment="Left" Padding="20,0"/> <Button Content="系统设置" Height="40" HorizontalContentAlignment="Left" Padding="20,0"/> </StackPanel> </Border> <!-- 右侧主内容区:2行1列Grid(产能卡片+数据表格) --> <Grid Grid.Column="1" Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- 产能卡片区:UniformGrid 2行2列均匀布局 --> <UniformGrid Grid.Row="0" Rows="2" Columns="2" Spacing="10" Margin="0,0,0,10"> <!-- 卡片1:总产量 --> <Border Background="#E3F2FD" CornerRadius="5" Padding="15"> <StackPanel> <TextBlock Text="总产量" FontSize="14" Foreground="#1976D2"/> <TextBlock Text="12345" FontSize="32" FontWeight="Bold" Margin="0,10,0,0"/> <TextBlock Text="较昨日 +5%" FontSize="12" Foreground="Green"/> </StackPanel> </Border> <!-- 卡片2:良品数 --> <Border Background="#E8F5E9" CornerRadius="5" Padding="15"> <StackPanel> <TextBlock Text="良品数" FontSize="14" Foreground="#388E3C"/> <TextBlock Text="12000" FontSize="32" FontWeight="Bold" Margin="0,10,0,0"/> <TextBlock Text="良率 97.2%" FontSize="12" Foreground="Green"/> </StackPanel> </Border> <!-- 卡片3:不良数 --> <Border Background="#FFEBEE" CornerRadius="5" Padding="15"> <StackPanel> <TextBlock Text="不良数" FontSize="14" Foreground="#D32F2F"/> <TextBlock Text="345" FontSize="32" FontWeight="Bold" Margin="0,10,0,0"/> <TextBlock Text="不良率 2.8%" FontSize="12" Foreground="Red"/> </StackPanel> </Border> <!-- 卡片4:运行时间 --> <Border Background="#FFF8E1" CornerRadius="5" Padding="15"> <StackPanel> <TextBlock Text="运行时间" FontSize="14" Foreground="#F57C00"/> <TextBlock Text="89.5h" FontSize="32" FontWeight="Bold" Margin="0,10,0,0"/> <TextBlock Text="稼动率 92%" FontSize="12" Foreground="Green"/> </StackPanel> </Border> </UniformGrid> <!-- 数据表格区:开启虚拟化的DataGrid --> <DataGrid Grid.Row="1" AutoGenerateColumns="False" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True" RowHeight="30"> <DataGrid.Columns> <DataGridTextColumn Header="序号" Binding="{Binding Index}" Width="60"/> <DataGridTextColumn Header="产品编号" Binding="{Binding ProductNo}" Width="120"/> <DataGridTextColumn Header="生产时间" Binding="{Binding ProduceTime}" Width="150"/> <DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="80"/> <DataGridTextColumn Header="操作员" Binding="{Binding Operator}" Width="100"/> </DataGrid.Columns> </DataGrid> </Grid> </Grid> <!-- 3. 底部状态栏 --> <Border Grid.Row="2" Background="#F5F5F5" BorderThickness="0,1,0,0" BorderBrush="#E0E0E0"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="系统运行正常" VerticalAlignment="Center" Margin="10,0"/> <TextBlock Grid.Column="1" Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='yyyy-MM-dd HH:mm:ss'}" VerticalAlignment="Center" Margin="0,0,10,0"/> </Grid> </Border> </Grid> </Window>

关键知识点

  • UniformGrid实现均匀分布的卡片布局
  • VirtualizingStackPanel开启虚拟化,支持 10 万 + 行数据流畅滚动
  • 多层Grid嵌套实现复杂的多区域布局
  • 样式复用和性能优化技巧

VirtualizingStackPanel 虚拟化原理详解

UI 虚拟化(UI Virtualization)是 WPF 提供的一种性能优化机制,核心思想是按需创建,即时回收。当ItemsControl(如DataGridListBox)包含大量数据项时,如果一次性为所有数据项创建对应的可视化元素(如DataGridRow),将消耗大量内存和 CPU 资源,导致界面卡顿甚至崩溃。虚拟化技术仅创建当前可视区域内的少量元素,当用户滚动时,离开可视区域的元素会被回收,并重新填充新进入可视区域的数据,从而大幅降低内存占用和 UI 线程压力。

容器回收(Container Recycling)是VirtualizationMode="Recycling"的进一步优化。默认的VirtualizationMode="Standard"在回收容器时,会丢弃旧容器并重新创建新容器,而Recycling模式会复用已有的容器对象,仅刷新其DataContext,避免了频繁创建/销毁对象的开销,是工业级大数据表格的首选配置。

C# 示例:为 DataGrid 绑定 10,000 条数据

publicpartialclassMonitorWindow:Window{publicMonitorWindow(){InitializeComponent();LoadLargeData();}privatevoidLoadLargeData(){// 生成 10000 条模拟生产数据vardata=newList<ProductRecord>();varrandom=newRandom();varstatuses=new[]{"合格","不合格","待检测"};varoperators=new[]{"张三","李四","王五","赵六"};for(inti=1;i<=10000;i++){data.Add(newProductRecord{Index=i,ProductNo=$"P{DateTime.Now:yyyyMMdd}-{i:D4}",ProduceTime=DateTime.Now.AddMinutes(-random.Next(0,1440)).ToString("yyyy-MM-dd HH:mm:ss"),Status=statuses[random.Next(statuses.Length)],Operator=operators[random.Next(operators.Length)]});}// 绑定到 DataGrid(需在 XAML 中给 DataGrid 设置 x:Name="ProductDataGrid")ProductDataGrid.ItemsSource=data;}}publicclassProductRecord{publicintIndex{get;set;}publicstringProductNo{get;set;}publicstringProduceTime{get;set;}publicstringStatus{get;set;}publicstringOperator{get;set;}}

配合 XAML 中DataGrid的虚拟化设置(VirtualizingStackPanel.IsVirtualizing="True"VirtualizationMode="Recycling"),即使绑定 10,000 条数据,滚动依然流畅,内存占用仅维持在可视区域的几十行左右。


学习路径建议

  1. 先完成入门级实例,掌握GridStackPanelBorder的基础用法
  2. 再做进阶级实例,学习数据绑定和自定义列表项
  3. 然后挑战高级实例,练习 Canvas 绝对布局和动态交互
  4. 最后研究工业级实例,掌握复杂界面的组织和性能优化
http://www.jsqmd.com/news/1334316/

相关文章:

  • WebExtensions消息传递机制详解:background与content scripts通信技巧
  • GCD队列切换从未如此简单:TaskQueue让主线程与后台线程无缝协作
  • 西安瓷砖空鼓松动不用全砸!全屋瓷砖翘边、起拱、渗水完整维修科普 - 宅安选房屋修缮
  • 【路径规划】基于模拟退火算法求解单中心的车辆路径规划问题matlab代码
  • RT60混响时间:从物理原理到声学测量的完整指南
  • CALM未来路线图:语义带宽扩展与多模态应用展望
  • 10分钟掌握dddpy测试策略:从单元测试到集成测试
  • 小程序开发平台有哪些:一份按业务成熟度整理的选择说明 - 维双云小凡
  • LabVIEW FPGA实战:高精度模拟量采集与PWM硬件级控制
  • mm目录下文件的主要功能
  • 什么是AI基础设施出海?企业如何选择全链路闭环的海外算力部署方案
  • 小程序模板平台哪个好?一套模板真正投入经营前,要过六道关 - 维双云小凡
  • Bleeding Edge Sample App完全解析:从安装到部署的一站式React项目指南
  • 终极Linux Wi-Fi适配器解决方案:rtl88x2bu驱动完全指南
  • 产品经理3天掌握SQL:提升数据驱动决策能力
  • 2026水转印加工公司推荐?优质厂商挑选指南 - 商业新知
  • 从Prompt到Agent:大模型应用开发工程师的工程落地指南
  • 数据分析师核心能力构建:从工具应用到业务驱动的完整实战指南
  • AMD GPU性能提升实战:ROCmLibs优化库5分钟配置指南
  • OpenXR-Toolkit架构解析:企业级VR应用性能优化40%实现原理
  • 2026荆门飘窗漏水渗水修缮指南|筑宅安房屋修缮,根治高层/老小区飘窗渗漏水难题 - 筑宅安
  • 小程序制作平台有哪些?2026年6款SaaS平台对比 - 维双云小凡
  • CentOS 7虚拟机文件复制报错“error when getting information”的深度排查与解决方案
  • Windows平台DB2 11.5完整安装与配置指南:从零搭建企业级数据库环境
  • PDF补丁丁:5个核心功能解决90%的PDF编辑难题
  • mir_eval核心功能解析:从节拍检测到和弦识别的完整评测方案
  • AI Agent开发全流程实战:从需求分析到生产部署的工程方法论
  • 洛雪音乐音源终极配置指南:5分钟打造全平台高品质音乐库
  • 3个必学的Blender贝塞尔曲线终极绘制技巧
  • 2026AI论文润色机构**单,CCF顶会发表选对少走弯路! - 小艾学姐