控件模版
一、什么是控件模板?
控件模板(ControlTemplate) 是 WPF 最核心的 UI 自定义技术,作用只有一个:
在不改变控件功能的前提下,100% 重写控件的外观和视觉结构。
在不改变控件功能的前提下,100% 重写控件的外观和视觉结构。
- 控件的逻辑(Button 点击、TextBox 输入、CheckBox 选中)完全不变
- 控件长什么样、由哪些元素组成,全部由你自己定义
- 是 WPF “逻辑与界面分离” 的灵魂
核心一句话
ControlTemplate = 控件的外观设计图纸
二、控件模板的核心作用
- 自定义任意控件外观
方形按钮 → 圆形按钮 → 图片按钮 → 动画按钮 - 统一项目 UI 风格
所有按钮、输入框、下拉框用一套模板,全局统一 - 实现复杂交互状态
鼠标悬浮、按下、禁用、选中、获得焦点等视觉效果 - 不写一行 C# 代码,纯 XAML 实现
三、控件模板必备知识点(必须掌握)
1. 核心属性
- 所属命名空间:
System.Windows.Controls - 父类:
FrameworkTemplate - 附加目标:
Control.Template属性
2. 必须写 TargetType
必须指定控件类型,例如:
1 TargetType="Button" 2 TargetType="TextBox" 3 TargetType="CheckBox"
3. 必须保留 “占位元素”(否则控件失效)
不同控件模板里必须放对应的占位符,否则功能丢失:
- 内容控件(Button/Label):
<ContentPresenter /> - 列表控件(ListBox):
<ItemsPresenter />
4. 模板绑定 TemplateBinding
用于把模板内的元素,关联到控件本身的属性。
1 {TemplateBinding Background}
2 {TemplateBinding Content}
3 {TemplateBinding IsEnabled}
作用:让控件的 Background、Content 等属性能传递到模板内部。
5. 触发器 Triggers
实现交互状态变化,比如鼠标放上去变色、按下变形。
常用触发器:
常用触发器:
Trigger:监听控件自身属性(IsMouseOver、IsPressed)DataTrigger:监听数据属性EventTrigger:监听事件
四、完整实战示例(从简单到复杂)
我带你做 3 个最常用的控件模板案例,可直接复制运行。
示例 1:最简单的控件模板(圆形按钮)
功能
把默认方形 Button → 圆角 / 圆形按钮,保留点击功能。
1 <Window.Resources>
2 <!-- 定义按钮控件模板 -->
3 <ControlTemplate x:Key="RoundButtonTemplate" TargetType="Button">
4 <!-- 外观结构:用 Border 做容器 -->
5 <Border CornerRadius="15"
6 Background="{TemplateBinding Background}"
7 BorderBrush="Black"
8 BorderThickness="2">
9
10 <!-- 内容占位:必须写,否则按钮文字不显示 -->
11 <ContentPresenter HorizontalAlignment="Center"
12 VerticalAlignment="Center"/>
13 </Border>
14 </ControlTemplate>
15 </Window.Resources>
16
17 <!-- 使用模板 -->
18 <Button Template="{StaticResource RoundButtonTemplate}"
19 Content="自定义圆形按钮"
20 Width="120" Height="40"
21 Background="LightBlue"/>
关键点
CornerRadius控制圆角ContentPresenter显示按钮文字 / 内容TemplateBinding让按钮的 Background 生效
示例 2:带交互状态的按钮模板(悬浮 + 按下 + 禁用)
这是实际项目最常用的完整按钮模板。
1 <Window.Resources>
2 <ControlTemplate x:Key="PerfectButtonTemplate" TargetType="Button">
3 <Border x:Name="border"
4 CornerRadius="10"
5 Background="LightSkyBlue"
6 BorderBrush="DarkBlue"
7 BorderThickness="2">
8
9 <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
10 </Border>
11
12 <!-- 触发器:状态变化 -->
13 <ControlTemplate.Triggers>
14 <!-- 鼠标悬浮 -->
15 <Trigger Property="IsMouseOver" Value="True">
16 <Setter TargetName="border" Property="Background" Value="SkyBlue"/>
17 <Setter TargetName="border" Property="BorderBrush" Value="Blue"/>
18 </Trigger>
19
20 <!-- 鼠标按下 -->
21 <Trigger Property="IsPressed" Value="True">
22 <Setter TargetName="border" Property="Background" Value="DeepSkyBlue"/>
23 <Setter TargetName="border" Property="BorderBrush" Value="DarkBlue"/>
24 </Trigger>
25
26 <!-- 按钮禁用 -->
27 <Trigger Property="IsEnabled" Value="False">
28 <Setter TargetName="border" Property="Background" Value="LightGray"/>
29 <Setter TargetName="border" Property="BorderBrush" Value="Gray"/>
30 <Setter Property="Foreground" Value="DarkGray"/>
31 </Trigger>
32 </ControlTemplate.Triggers>
33 </ControlTemplate>
34 </Window.Resources>
35
36 <!-- 使用 -->
37 <Button Template="{StaticResource PerfectButtonTemplate}"
38 Content="带状态的按钮"
39 Width="140" Height="40" Margin="10"/>
40
41 <Button Template="{StaticResource PerfectButtonTemplate}"
42 Content="禁用按钮"
43 IsEnabled="False"
44 Width="140" Height="40"/>
效果
- 正常:浅蓝色
- 悬浮:中蓝色
- 按下:深蓝色
- 禁用:灰色
示例 3:自定义 TextBox 模板(去掉默认边框)
很多项目需要把输入框改成极简风格。
1 <ControlTemplate x:Key="FlatTextBoxTemplate" TargetType="TextBox">
2 <Border CornerRadius="5"
3 Background="White"
4 BorderBrush="LightGray"
5 BorderThickness="1">
6
7 <ScrollViewer x:Name="PART_ContentHost"/> <!-- 必须保留! -->
8 </Border>
9
10 <ControlTemplate.Triggers>
11 <Trigger Property="IsFocused" Value="True">
12 <Setter Property="BorderBrush" Value="Blue"/>
13 <Setter Property="BorderThickness" Value="2"/>
14 </Trigger>
15 </ControlTemplate.Triggers>
16 </ControlTemplate>
17
18 <!-- 使用 -->
19 <TextBox Template="{StaticResource FlatTextBoxTemplate}"
20 Width="200" Height="35"
21 PlaceholderText="请输入内容"/>
重点
TextBox 模板必须保留:
1 <ScrollViewer x:Name="PART_ContentHost"/>
这是输入框的文字容器,不写就无法输入文字!
五、控件模板 + Style(最常用用法)
实际开发中,模板一般写在 Style 里,实现全局自动应用。
1 <!-- 全局按钮样式 + 模板 --> 2 <Style TargetType="Button"> 3 <Setter Property="Width" Value="120"/> 4 <Setter Property="Height" Value="35"/> 5 <Setter Property="Foreground" Value="White"/> 6 7 <!-- 应用模板 --> 8 <Setter Property="Template"> 9 <Setter.Value> 10 <ControlTemplate TargetType="Button"> 11 <Border CornerRadius="8" Background="#FF409EFE"> 12 <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> 13 </Border> 14 </ControlTemplate> 15 </Setter.Value> 16 </Setter> 17 </Style>
之后页面里所有 Button 自动变美观,无需单独设置 Template!
六、控件模板核心总结(必背)
- ControlTemplate 只改外观,不改功能
- 必须写
TargetType - 必须保留占位元素:
- Button:
ContentPresenter - TextBox:
PART_ContentHost
- Button:
TemplateBinding关联控件属性Triggers实现交互状态- 配合
Style实现全局复用
浙公网安备 33010602011771号