WPF中的样式(Style)和模板(Template)都是用于定制控件外观的核心机制,但两者的定位和作用范围有明显差异,同时也存在相互配合的使用场景。

WPF样式的定义与作用
样式本质是一组属性值的集合,用于批量设置同一类控件的公共属性,避免重复编写相同的属性配置。样式可以包含触发器(Trigger),根据控件的状态动态修改属性值。
比如我们需要让所有按钮的背景色为浅蓝色,鼠标悬停时变为深蓝色,就可以定义一个通用样式:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!-- 定义按钮通用样式 -->
<Style TargetType="Button">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="5"/>
<!-- 触发器:鼠标悬停时修改背景色 -->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkBlue"/>
<Setter Property="Foreground" Value="White"/>
<Trigger>
</Style.Triggers>
<Style>
</Window.Resources>
<StackPanel>
<Button Content="按钮1"/>
<Button Content="按钮2"/>
<Button Content="按钮3"/>
</StackPanel>
</Window>
WPF模板的定义与作用
模板分为控件模板(ControlTemplate)和数据模板(DataTemplate),其中控件模板用于定义控件的视觉结构和视觉行为,决定控件由哪些子元素组成、如何布局。默认的控件模板定义了按钮是矩形带文字、文本框是矩形可输入等基础外观,自定义模板可以完全重写这些结构。
比如我们可以自定义一个圆形按钮的控件模板:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!-- 定义圆形按钮的控件模板 -->
<ControlTemplate TargetType="Button" x:Key="CircleButtonTemplate">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Content="圆形按钮"
Template="{StaticResource CircleButtonTemplate}"
Background="LightGreen"
Width="80" Height="80"
Margin="10"/>
</StackPanel>
</Window>
样式和模板的核心区别
| 对比维度 | 样式(Style) | 模板(ControlTemplate) |
|---|---|---|
| 作用范围 | 设置控件的现有属性,不改变控件的视觉结构 | 重写控件的视觉结构,定义控件由哪些子元素构成 |
| 核心组成 | Setter集合、Trigger集合 | 视觉树结构、TemplateBinding绑定 |
| 适用场景 | 批量统一控件的属性值,处理状态变化 | 完全自定义控件的 appearance,实现特殊形状的控件 |
| 属性依赖 | 依赖控件已有的可设置属性 | 可以定义全新的子元素,不依赖原有控件结构 |
样式和模板的联系
样式和模板并不是独立存在的,两者经常配合使用:
- 样式中可以包含
ControlTemplate类型的Setter,把模板作为样式的一部分,这样引用样式的同时就会应用对应的模板,不需要单独指定Template属性。 - 模板中可以通过
TemplateBinding绑定到样式中设置的属性,让模板的外观可以跟随样式配置动态变化,提升复用性。 - 两者都定义在资源中,可以被多个控件复用,减少重复代码。
下面的示例展示了样式中嵌入模板的用法:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!-- 样式中嵌入控件模板 -->
<Style TargetType="Button" x:Key="RoundButtonStyle">
<Setter Property="Background" Value="LightCoral"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border CornerRadius="50"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style>
</Window.Resources>
<StackPanel>
<Button Content="样式带模板" Style="{StaticResource RoundButtonStyle}" Margin="10"/>
<Button Content="复用样式" Style="{StaticResource RoundButtonStyle}" Background="LightYellow" Margin="10"/>
</StackPanel>
</Window>
使用总结
在实际开发中,如果只需要调整控件的颜色、大小、边距等现有属性,优先使用样式;如果需要改变控件的整体形状、添加新的子元素、完全重写视觉结构,就需要使用控件模板。同时可以把模板嵌入到样式中,实现样式和模板的统一复用,让界面代码更简洁易维护。
WPF样式模板ControlTemplateStyle修改时间:2026-07-14 21:12:37