控件模版

一、什么是控件模板?

控件模板(ControlTemplate) 是 WPF 最核心的 UI 自定义技术,作用只有一个:
在不改变控件功能的前提下,100% 重写控件的外观和视觉结构。
  • 控件的逻辑(Button 点击、TextBox 输入、CheckBox 选中)完全不变
  • 控件长什么样、由哪些元素组成,全部由你自己定义
  • 是 WPF “逻辑与界面分离” 的灵魂

核心一句话

ControlTemplate = 控件的外观设计图纸

二、控件模板的核心作用

  1. 自定义任意控件外观
    方形按钮 → 圆形按钮 → 图片按钮 → 动画按钮
  2. 统一项目 UI 风格
    所有按钮、输入框、下拉框用一套模板,全局统一
  3. 实现复杂交互状态
    鼠标悬浮、按下、禁用、选中、获得焦点等视觉效果
  4. 不写一行 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!

六、控件模板核心总结(必背)

  1. ControlTemplate 只改外观,不改功能
  2. 必须写 TargetType
  3. 必须保留占位元素:
    • Button:ContentPresenter
    • TextBox:PART_ContentHost
  4. TemplateBinding 关联控件属性
  5. Triggers 实现交互状态
  6. 配合 Style 实现全局复用
posted on 2026-03-26 09:35  工业搬砖猿Lee  阅读(39)  评论(0)    收藏  举报