WinForm到WPF的转型,需要开发者从基于控件的传统概念,转变到注重界面布局、数据绑定、可视化树等全新的思路。以下主要围绕 WPF 的 Expander 控件进行实战说明,并结合对应样式与常见用法的示例进行讲解。
迁移思维:从WinForm到WPF
在 WinForm 中,我们通常通过拖拽控件到窗体上,然后在属性面板中进行部分设置。
在 WPF 中,界面更重视「布局」与「控件间的层次结构」。我们会使用 XAML 来描述界面,并通过“布局容器(如 Grid、StackPanel、DockPanel 等)”来协调控件的摆放。
在 WinForm 中,样式主题化往往依靠第三方库或通用的 UI 框架。
在 WPF 中,样式与控件模板(ControlTemplate/Style)是平台内置的能力,可以直接通过 XAML 配置,实现对外观与布局的深层定制。
Expander控件介绍
Expander 控件可以折叠或展开内容区,常用于在界面上分层展示、收起和隐藏相对不常用的子内容,以达到节省空间、提高用户交互体验的目的。
Expander 的基本结构
通常情况下,Expander 的主要结构和要点包括:
Header
:Expander 的标题区域,会一直显示在界面上。Content
:Expander 的主体内容,显示在 Header 下方。可以是任何 UI 元素或容器。
下面是一个简单的 Expander 示例:
<Window x:Class="AppExpander.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:AppExpander"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Margin="10">
<!-- 在Grid内放置一个Expander -->
<Expander Header="设置选项"
ExpandDirection="Down"
Background="AliceBlue"
Foreground="Black"
IsExpanded="True">
<!-- Expander折叠/展开的内容 -->
<StackPanel Margin="5">
<!-- 在这里可以放置各种元素 -->
<TextBlock Text="这是Expander的内容。"
Margin="0,0,0,5"/>
<Button Content="按钮1" Margin="0,0,0,5"/>
<Button Content="按钮2"/>
</StackPanel>
</Expander>
</Grid>
</Window>
关键属性
Header
:设置标题,这里可以是文本,也可以是任何 UI 元素。Content
ExpandDirection
:指定展开的方向,一般是 Down
、Up
、Left
、Right
。IsExpanded
:控制是否默认展开,为 true
时默认展开,为 false
时则默认折叠。
Expander在复杂界面中的应用
WPF 提供多种布局容器(如 Grid
、StackPanel
、Border
、DockPanel
等),通常可以搭配 Expander 使用。以下示例演示如何在 Grid 中使用多个 Expander:
<Window x:Class="AppExpander.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:AppExpander"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- 第一个Expander,展开方向向下 -->
<Expander Header="工具栏设置"
ExpandDirection="Down"
IsExpanded="True"
Background="LightYellow"
Grid.Row="0">
<StackPanel Margin="5">
<TextBlock Text="工具栏相关设置" />
<CheckBox IsChecked="True" Content="显示工具栏"/>
<CheckBox IsChecked="False" Content="启用悬浮功能"/>
</StackPanel>
</Expander>
<!-- 第二个Expander,展开方向向上 -->
<Expander Header="高级选项"
ExpandDirection="Up"
IsExpanded="False"
Background="Lavender"
Grid.Row="1">
<StackPanel Margin="5">
<TextBlock Text="高级特性配置" />
<CheckBox IsChecked="True" Content="启用网格线"/>
<CheckBox IsChecked="False" Content="启用日志记录"/>
</StackPanel>
</Expander>
<!-- 第三行放其它内容 -->
<TextBlock Text="主内容区"
Background="AliceBlue"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="2"/>
</Grid>
</Window>

上面演示了将两个方向不同的 Expander 放在同一个 Grid 中,并结合不同的行,把布局做得更加清晰。
自定义Expander样式
WPF 中的样式(Style)能帮助我们快速统一多个相似控件的外观。下面示例演示如何通过简单样式修改 Expander 的外观。
<Window x:Class="WpfDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Expander样式示例" Height="350" Width="400">
<Window.Resources>
<!-- 定义Expander的样式 -->
<Style TargetType="Expander" x:Key="MyExpanderStyle">
<!-- 设置常见属性 -->
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="DarkBlue"/>
<Setter Property="FontWeight" Value="Bold"/>
<!-- 使用Setter改变展开箭头的位置与视觉等 -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Expander">
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="4">
<DockPanel>
<!-- 这里的ToggleButton是Expander折叠/展开的标题按钮 -->
<ToggleButton x:Name="ExpanderToggleButton"
DockPanel.Dock="Top"
Content="{TemplateBinding Header}"
FontWeight="{TemplateBinding FontWeight}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"/>
<!-- 展开的内容放在ContentPresenter里 -->
<ContentPresenter x:Name="ExpanderContent"
Visibility="Collapsed"
DockPanel.Dock="Bottom"/>
</DockPanel>
<ControlTemplate.Triggers>
<!-- 当Expander展开时,显示 内容区域 -->
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ExpanderContent" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Margin="10">
<StackPanel>
<Expander Header="样式化的Expander1" Style="{StaticResource MyExpanderStyle}">
<TextBlock Text="这里是Expander内容1" Margin="10"/>
</Expander>
<Expander Header="样式化的Expander2" Style="{StaticResource MyExpanderStyle}">
<StackPanel Margin="10">
<TextBlock Text="这里是Expander内容2"/>
<Button Content="操作 Button"/>
</StackPanel>
</Expander>
</StackPanel>
</Grid>
</Window>
以上示例设置了一个自定义的 Template,使得 Expander 的箭头按钮被替换为最基础的 ToggleButton,开发者可以在此基础上添加复杂的视觉效果。值得注意的是,在实际项目中,常常需要更精细的控件模板(例如修改箭头的方向图标、增加动画等)。
数据绑定与事件
Expander 也支持数据绑定与命令绑定,如果需要在展开或折叠时执行逻辑,可以通过以下事件进行处理:
示例(在展开和折叠时做简单提示):
<Window x:Class="WpfDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Expander事件示例" Height="300" Width="400">
<Grid Margin="10">
<Expander Header="点击展开/收起" Expanded="Expander_Expanded" Collapsed="Expander_Collapsed">
<StackPanel Margin="5">
<TextBlock Text="此处显示更多选项..." />
</StackPanel>
</Expander>
</Grid>
</Window>
在 MainWindow.xaml.cs
中,添加对应的事件处理程序:
using System.Windows;
namespace WpfDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
// 当Expander展开时的事件处理
MessageBox.Show("Expander 已展开!");
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
// 当Expander收起时的事件处理
MessageBox.Show("Expander 已收起!");
}
}
}
总结
- WinForm 迁移到 WPF,需要改变对界面开发的认识,着重掌握布局与 XAML 树状结构。
- Expander 能有效优化界面空间,适用于各种折叠/展开场景。
- WPF 的 Style 和 ControlTemplate 功能,为 Expander 提供了高度可定制化的可能。
- 事件与数据绑定也与其它 WPF 控件一致,逻辑部分则仍编写在 C# 代码后端中。
通过以上示例,期望能帮助正从 WinForm 向 WPF 转型的开发者更好地理解与运用 Expander,在界面布局、样式以及互动逻辑上进一步提升开发能力。
阅读原文:原文链接
该文章在 2025/5/7 17:55:37 编辑过