惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
小众软件
小众软件
MongoDB | Blog
MongoDB | Blog
Hugging Face - Blog
Hugging Face - Blog
Jina AI
Jina AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
量子位
A
About on SuperTechFans
G
Google Developers Blog
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - zhaotianff

WPF控件样式和模板全解析-ToolTip控件 WPF控件样式和模板全解析-RadioButton控件 WPF控件样式和模板全解析-ToggleButton控件 WPF控件样式和模板全解析-CheckBox控件 软件架构风格与软件架构设计方法 WPF控件样式和模板全解析-Button控件 Windows一直卡在检查更新的解决方案 - zhaotianff - 博客园 AI时代,程序员应该何去何从? C++中的explicit关键字 如何解决Windows 10/11 删除打印机时,拒绝访问的问题 解决IIS服务器typecho上传附件后无法访问的问题 Visual Studio编译过程中拷贝文件的一些实用小技巧 Jenkins快速入门教程 .NET是什么?为什么要选择.NET? 如何在WPF中实现类似DevOps的自动化流程 一文带你搞懂医疗器械设计开发全生命周期 Windows如何清除本机记录的git用户名和密码 HL7协议详解 医疗行业 GDT 数据格式详解 一文带你搞懂C# 异步编程(async/await)底层原理 如何在C#中使用Chromium headless(无头模式)浏览器 不同.NET版本中的WPF新增功能 如何在WPF中使用 Fluent 主题 Windows平台下的各种原生UI框架介绍 C#如何Hook托管函数 WinDbg 用户层调试进阶教程 Windows编程的一些基础理论 推荐一款优秀的Windows经典文件管理器项目-WinFile Windows如何阻止应用程序联网 如何在WPF中捕获窗口外的事件
WPF控件样式和模板全解析-Label控件
zhaotianff · 2026-08-27 · via 博客园 - zhaotianff

可能有些小伙伴觉得Label控件比较简单,不需要再单独介绍它的样式和模板。

这里呢,我还是觉得很有必要拿出来讲一下,通过剖析它的内部模板,来了解Label控件更深层次的原理。

Label控件的默认样式和模板

依旧是使用Blend获取默认的样式和模板,如下所示:

 1   <Style x:Key="LabelStyle1" TargetType="{x:Type Label}">
 2       <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
 3       <Setter Property="Background" Value="Transparent"/>
 4       <Setter Property="Padding" Value="5"/>
 5       <Setter Property="HorizontalContentAlignment" Value="Left"/>
 6       <Setter Property="VerticalContentAlignment" Value="Top"/>
 7       <Setter Property="Template">
 8           <Setter.Value>
 9               <ControlTemplate TargetType="{x:Type Label}">
10                   <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
11                       <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
12                   </Border>
13                   <ControlTemplate.Triggers>
14                       <Trigger Property="IsEnabled" Value="false">
15                           <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
16                       </Trigger>
17                   </ControlTemplate.Triggers>
18               </ControlTemplate>
19           </Setter.Value>
20       </Setter>
21   </Style>

拆解Button样式和模板

从上面的样式可以看到,Label控件的模板和Button控件几乎一样,都是Border里面套一个ContentPresenter控件

1  <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
2       <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
3 </Border>

然后就是一个触发器,用于设置禁用状态下Label控件文字的颜色

1 <ControlTemplate.Triggers>
2     <Trigger Property="IsEnabled" Value="false">
3          <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
4     </Trigger>
5 </ControlTemplate.Triggers>

Label和TextBlock的区别

一直就听说TextBlock是轻量级的文本显示控件,Label更重量级。

但是根据前面文章中,关于ContentPresenter控件的介绍就可以知道:ContentPresenter控件只是一个壳,在显示文本时最终还是使用的TextBlock控件。

那为什么还是会有这个说法呢?

原因有以下几个方面:

1、继承链不同,TextBlock的继承关系更简单,Label更复杂

  • TextBlock 直接继承自 FrameworkElement。它处于WPF元素体系的最底层,属于“呈现元素”,只负责把自己画在屏幕上。

  • Label 继承自 ContentControl,完整的继承关系是ContentControl->Control->FrameworkElement,而Control控件拥有更多的依赖属性及其它特性,所以它的开销就会大一点,相比之下,TextBlock的功能就更单一。

2、视觉树的层级深度

      TextBlock只有一层,而Label控件会有Label->Border->ContentPresenter->TextBlock多层。

      WPF的布局过程(Measure和Arrange)会递归遍历视觉树,所以每多一层嵌套,CPU就需要多做一次计算。

      通常情况下,对于单个Label影响不大,但是当数量比较多时,例如大量的ListBoxDataGrid列表项时,就会对性能造成一定的影响。

3、焦点处理开销

     Label默认Focusable=true,TextBlock默认Focusable=false,

     而且Label可以使用助记快捷键 AccessKey功能,例如下面的代码,按按下键盘上的Alt+H时,可以快速将光标定位至TextBox元素。

1  <StackPanel>
2      <Label  Content="_HelloWorld" Target="{Binding ElementName=tbox2}"></Label>
3      <TextBox x:Name="tbox2"></TextBox>
4  </StackPanel>

动画

4、布局计算问题

  • TextBlock 的测量逻辑较专一,只计算文字的宽高。

  • Label 属于内容控件,可以所以放置任意控件,如图片、布局面板等。这就导致在计算界面布局时,它的测量算法比TextBlock复杂。