从WinForm迁移到WPF是很多.NET开发者都会经历的过程。WPF提供了更强大和灵活的布局系统,但对于习惯了WinForm的开发者来说,可能需要一些时间来适应。本文将详细介绍WPF布局嵌套的核心技巧。
WPF主要的布局容器包括:
C#// WinForm中的控件定位
button1.Location = new Point(100, 100);
button1.Size = new Size(80, 25);
XML<!-- WPF中的控件定位 -->
<Button Margin="100,100,0,0" Width="80" Height="25"/>
XML<Window x:Class="WpfDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="布局嵌套示例" Height="450" Width="800">
<!-- 最外层使用DockPanel -->
<DockPanel LastChildFill="True">
<!-- 顶部工具栏 -->
<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button Content="新建"/>
<Button Content="保存"/>
<Separator/>
<Button Content="退出"/>
</ToolBar>
</ToolBarTray>
<!-- 左侧导航栏 -->
<StackPanel DockPanel.Dock="Left" Width="200" Background="LightGray">
<TreeView Height="200">
<TreeViewItem Header="项目1">
<TreeViewItem Header="子项1"/>
<TreeViewItem Header="子项2"/>
</TreeViewItem>
<TreeViewItem Header="项目2"/>
</TreeView>
</StackPanel>
<!-- 右侧主要内容区域 -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 内容区域使用Grid布局 -->
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5"/> <!-- 分隔条 -->
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 左侧内容 -->
<TextBox Grid.Column="0"
AcceptsReturn="True"
TextWrapping="Wrap"
Margin="5"/>
<!-- 分隔条 -->
<GridSplitter Grid.Column="1"
Width="5"
HorizontalAlignment="Stretch"/>
<!-- 右侧内容 -->
<DockPanel Grid.Column="2">
<TextBlock DockPanel.Dock="Top"
Text="预览区域"
Background="LightBlue"
Padding="5"/>
<Border BorderBrush="Gray"
BorderThickness="1"
Margin="5">
<ScrollViewer>
<TextBlock Text="预览内容"
Margin="5"/>
</ScrollViewer>
</Border>
</DockPanel>
</Grid>
<!-- 底部状态栏 -->
<StatusBar Grid.Row="1">
<StatusBarItem>
<TextBlock Text="就绪"/>
</StatusBarItem>
<Separator/>
<StatusBarItem>
<ProgressBar Width="100" Height="15" Value="45"/>
</StatusBarItem>
</StatusBar>
</Grid>
</DockPanel>
</Window>
XML<!-- Grid布局中的跨行跨列 -->
<Button Grid.Row="1" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="3"/>
<!-- DockPanel中的停靠 -->
<TextBlock DockPanel.Dock="Top"/>
<!-- 控件的对齐方式 -->
<Button HorizontalAlignment="Center" VerticalAlignment="Center"/>
使用Margin和Padding控制间距
XML<!-- 外边距 -->
<Button Margin="5,10,5,10"/>
<!-- 内边距 -->
<Border Padding="10">
<TextBlock Text="内容"/>
</Border>
XML<Grid>
<Grid.ColumnDefinitions>
<!-- 使用比例布局 -->
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 控件会随窗口大小自动调整 -->
<Button Grid.Column="0" Content="按钮1"/>
<Button Grid.Column="1" Content="按钮2"/>
<Button Grid.Column="2" Content="按钮3"/>
</Grid>
XML<DockPanel>
<ToolBar DockPanel.Dock="Top">
<Button Content="工具栏固定"/>
</ToolBar>
<ScrollViewer>
<StackPanel>
<!-- 大量内容 -->
<TextBlock Text="内容1"/>
<TextBlock Text="内容2"/>
<!-- 更多内容 -->
</StackPanel>
</ScrollViewer>
</DockPanel>
XML<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 第一行 -->
<TextBlock Grid.Row="0" Grid.Column="0" Text="用户名:"
VerticalAlignment="Center" Margin="5"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="5"/>
<!-- 第二行 -->
<TextBlock Grid.Row="1" Grid.Column="0" Text="密码:"
VerticalAlignment="Center" Margin="5"/>
<PasswordBox Grid.Row="1" Grid.Column="1" Margin="5"/>
<!-- 第三行 -->
<StackPanel Grid.Row="2" Grid.Column="1"
Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="确定" Margin="5"/>
<Button Content="取消" Margin="5"/>
</StackPanel>
</Grid>
Markdown<Window x:Class="AppLayoutNesting.Window1"
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:AppLayoutNesting"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Window.Resources>
<!-- 渐变背景样式 -->
<LinearGradientBrush x:Key="HeaderGradient" StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#1976D2" Offset="0"/>
<GradientStop Color="#2196F3" Offset="1"/>
</LinearGradientBrush>
<!-- 导航项样式 -->
<Style x:Key="NavItemStyle" TargetType="ListBoxItem">
<Setter Property="Padding" Value="15,12"/>
<Setter Property="Margin" Value="0,2"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border"
CornerRadius="8"
Background="{TemplateBinding Background}">
<ContentPresenter Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#E3F2FD"/>
<Setter Property="Foreground" Value="#1976D2"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#F5F5F5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 数据卡片样式 -->
<Style x:Key="DataCardStyle" TargetType="Border">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="12"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="15"
ShadowDepth="2"
Direction="270"
Color="#20000000"
Opacity="0.2"/>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 顶部标题栏 -->
<Border Grid.Row="0"
Background="{StaticResource HeaderGradient}"
>
<Grid Margin="20,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="能源管理看板"
FontSize="26"
FontWeight="SemiBold"
Foreground="White"/>
<TextBlock Text="实时监控中"
Margin="20,0,0,0"
VerticalAlignment="Center"
Foreground="#A7E3FF"/>
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="最后更新时间:"
Foreground="#E3F2FD"/>
<TextBlock Text="2024-01-20 15:30:45"
Foreground="#FFFFFF"/>
</StackPanel>
</Grid>
</Border>
<!-- 主要内容区域 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="280"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 左侧导航面板 -->
<Border Grid.Column="0"
Background="White"
Margin="15,15,7.5,15"
CornerRadius="12"
>
<StackPanel Margin="15,20">
<TextBlock Text="监控面板"
FontSize="20"
FontWeight="SemiBold"
Margin="15,0,0,20"/>
<ListBox BorderThickness="0"
Background="Transparent">
<ListBoxItem Content="⚡ 电力消耗" Style="{StaticResource NavItemStyle}"/>
<ListBoxItem Content="💧 水资源使用" Style="{StaticResource NavItemStyle}"/>
<ListBoxItem Content="🔥 天然气使用" Style="{StaticResource NavItemStyle}"/>
<ListBoxItem Content="🌱 碳排放监测" Style="{StaticResource NavItemStyle}"/>
</ListBox>
</StackPanel>
</Border>
<!-- 右侧内容区域 -->
<Grid Grid.Column="1" Margin="7.5,15,15,15">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 电力消耗卡片 -->
<Border Grid.Row="0" Grid.Column="0"
Style="{StaticResource DataCardStyle}">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel>
<TextBlock Text="实时用电量"
FontSize="18"
FontWeight="SemiBold"/>
<TextBlock Text="↑ 5.2%"
Foreground="#FF4081"
HorizontalAlignment="Right"/>
</DockPanel>
<StackPanel Grid.Row="1"
VerticalAlignment="Center">
<TextBlock Text="75.8"
FontSize="36"
FontWeight="Bold"
Foreground="#1976D2"/>
<TextBlock Text="千瓦时 (kWh)"
Foreground="#666666"
Margin="0,5"/>
</StackPanel>
<TextBlock Grid.Row="2"
Text="同比上周增长5.2%"
Foreground="#666666"/>
</Grid>
</Border>
<!-- 水资源使用卡片 -->
<Border Grid.Row="0" Grid.Column="1"
Style="{StaticResource DataCardStyle}">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel>
<TextBlock Text="当日用水量"
FontSize="18"
FontWeight="SemiBold"/>
<TextBlock Text="↓ 3.1%"
Foreground="#4CAF50"
HorizontalAlignment="Right"/>
</DockPanel>
<StackPanel Grid.Row="1"
VerticalAlignment="Center">
<TextBlock Text="128.5"
FontSize="36"
FontWeight="Bold"
Foreground="#00BCD4"/>
<TextBlock Text="立方米 (m³)"
Foreground="#666666"
Margin="0,5"/>
</StackPanel>
<TextBlock Grid.Row="2"
Text="同比上周减少3.1%"
Foreground="#666666"/>
</Grid>
</Border>
<!-- 天然气使用卡片 -->
<Border Grid.Row="1" Grid.Column="0"
Style="{StaticResource DataCardStyle}">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel>
<TextBlock Text="天然气用量"
FontSize="18"
FontWeight="SemiBold"/>
<TextBlock Text="↑ 2.8%"
Foreground="#FF4081"
HorizontalAlignment="Right"/>
</DockPanel>
<StackPanel Grid.Row="1"
VerticalAlignment="Center">
<TextBlock Text="256.3"
FontSize="36"
FontWeight="Bold"
Foreground="#FF9800"/>
<TextBlock Text="立方米 (m³)"
Foreground="#666666"
Margin="0,5"/>
</StackPanel>
<TextBlock Grid.Row="2"
Text="同比上周增长2.8%"
Foreground="#666666"/>
</Grid>
</Border>
<!-- 碳排放监测卡片 -->
<Border Grid.Row="1" Grid.Column="1"
Style="{StaticResource DataCardStyle}">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel>
<TextBlock Text="碳排放量"
FontSize="18"
FontWeight="SemiBold"/>
<TextBlock Text="↓ 1.5%"
Foreground="#4CAF50"
HorizontalAlignment="Right"/>
</DockPanel>
<StackPanel Grid.Row="1"
VerticalAlignment="Center">
<TextBlock Text="1.28"
FontSize="36"
FontWeight="Bold"
Foreground="#4CAF50"/>
<TextBlock Text="吨 (t)"
Foreground="#666666"
Margin="0,5"/>
</StackPanel>
<TextBlock Grid.Row="2"
Text="同比上周减少1.5%"
Foreground="#666666"/>
</Grid>
</Border>
</Grid>
</Grid>
</Grid>
</Window>
XML<!-- 禁用布局计算 -->
<StackPanel UseLayoutRounding="True">
<!-- 内容 -->
</StackPanel>
<!-- 缓存布局结果 -->
<Grid CacheMode="BitmapCache">
<!-- 内容 -->
</Grid>
WPF的布局系统虽然比WinForm复杂,但提供了更强大的功能和更好的灵活性。掌握布局嵌套技巧可以帮助我们:
关键是要转变思维方式,从固定坐标的思维转向容器布局的思维。通过合理使用布局容器的嵌套,我们可以构建出既美观又实用的WPF应用程序。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!