XAML是基于XML的语言,其遵循并扩展了XML的语法规则。其中一项扩展就是标记扩展(Markup Extension),比如我们经常使用的绑定Bindingx:Type

什么是标记扩展

标记扩展允许在XAML标记中使用特殊的语法来动态地为特性(Attribute)赋值或执行其他操作。简单来说,在XAML中,所有为XAML元素特性(Attribute)赋值时,使用花括号{}包裹起来的语句就是标记扩展。这么定义不是特别严谨,因为转义序列也是以花括号{}作为标记的,但不是标记扩展。[1] 后边提到的x:Array标记扩展使用的是<>。

标记扩展的语法是{标记扩展类 参数},所有的标记扩展类都是派生自System.Windows.MarkupExtension基类实现的。开篇提到的Bindingx:Type都是WPF框架内置的标记扩展。细心的朋友会发现这两个标记扩展一个带x:前缀,一个不带。这就不得不提WPF中的两类标记扩展。

  • XAMl定义的标记扩展
  • 特定于 WPF 的标记扩展。

XAML定义的标记扩展

XAML定义的标记扩展在System.Xaml程序集中,位于XAML命名空间内,并非WPF特定的实现。这类标记扩展通常由x:前缀标识。主要有以下几种:

  • x:Static 用于引用以符合公共语言规范 (CLS) 的方式定义的任何静态按值代码实体。 可使用引用的静态属性在 XAML 中提供属性的值。
  • x:Type 为命名类型提供 Type 对象。此扩展最常用于样式和模板。
  • x:Array 通过标记扩展提供对 XAML 中对象的数组的一般支持。需要注意的是,在 XAML 2009 中,x:Array定义为语言基元而不是标记扩展。[2]
  • x:Null 将 null 指定为属性的值,可用于特性或属性元素值。

特定于WPF的标记扩展

最常见的标记扩展是支持资源引用的标记扩展(StaticResource 和 DynamicResource),和支持数据绑定的标记扩展 (Binding)。特定于WPF的标记扩展有以下几种:[3]

  • StaticResource 通过查找对已定义资源的引用,为任何 XAML 属性提供值。 查找该资源的行为类似于加载时查找,将查找当前 XAML 页面先前的标记以及其他应用程序源中加载的资源,并将生成该资源值作为运行时对象中的属性值。该标记扩展要求引用的资源必须在引用之前声明,否则加载时找不到资源报错。
  • DynamicResource 通过将值推迟为对资源的运行时引用来为属性提供值。 动态资源引用强制在每次访问此类资源时都进行新查找。该标记扩展引用的资源则对声明的位置没有太多要求,因为它在运行的时候采取查找资源。
  • Binding 将属性值延迟为数据绑定值,创建中间表达式对象并在运行时解释应用于元素及其绑定的数据上下文。此标记扩展相对复杂,因为它会启用大量内联语法来指定数据绑定。
  • RelativeSource 在设置 XAML 中创建的 Binding 元素的 RelativeSource 属性时使用。例如嵌套在 Binding 扩展内
<object property="{Binding RelativeSource={RelativeSource modeEnumValue} ...}" ... />
  • TemplateBinding 使控件模板能够使用模板化属性的值,这些属性来自于将使用该模板的类的对象模型定义属性。换言之,模板定义中的属性可访问仅在应用了模板之后才存在的上下文。
  • ColorConvertedBitmap 提供方法来指定没有嵌入配置文件的位图源。 颜色上下文/配置文件由 URI 指定,与图像源 URI 一样。
<object property="{ColorConvertedBitmap imageSource sourceIIC destinationIIC}" ... />
  • ComponentResourceKey 定义和引用从外部程序集加载的资源的键。 这使资源查找能够在程序集中指定目标类型,而不是在程序集中或类上指定显式资源字典。
  • ThemeDictionary 为集成第三方控件的自定义控件创作者或应用程序提供一种方法,用于加载要在设置控件样式时使用的特定于主题的资源字典。

自定义标记扩展

上文提到所有的标记扩展类都是派生自System.Windows.MarkupExtension基类实现的。因此自定义标记扩展也需派生自这个基类。MarkupExtension仅提供一个简单的ProvideValue(IServiceProvider serviceProvider)方法来获取所期望的数值。接下来用个简单的例子进行说明:

public class AddExtension : MarkupExtension
{
private string _value; private string _value1; public string Value1
{
get => _value1;
set => _value1 = value;
} public AddExtension()
{ } public AddExtension(string par)
{
_value = par;
} public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_value == null) { throw new InvalidOperationException(); } int iv, iv1;
if (int.TryParse(_value, out iv) && int.TryParse(Value1, out iv1))
{
return iv + iv1;
}
else
return _value;
}
}

这个自定义的标记扩展定义了一个带参构造函数和一个属性用于接收参数,并通过重写ProvideValue方法返回两个参数的和。以下代码是使用该标记扩展的示例。

<Button Content="{local:Add 2,Value1=5}"/>

根据约定,标记扩展的命名都是以Extension结尾,在引用扩展类时可以省略最后一个单词Extension,示例中紧跟在local:Add后的2是作为构造函数的参数,Value1=5则是给标记扩展中定义的属性Value1赋值。

小结

本文介绍了WPF的基础概念标记扩展,并列举了WPF框架内置了两大类标记扩展。最后用一个不太有实际意义的简单示例展示了如何自定义标记扩展。由于MarkupExtension并非派生自DependencyObject,因此不能直接定义依赖属性,但可以通过定义一个依赖对象结合附加属性的方式实现扩展标记属性的绑定。

参考


  1. https://learn.microsoft.com/zh-cn/dotnet/desktop/xaml-services/escape-sequence-markup-extension

  2. https://learn.microsoft.com/zh-cn/dotnet/desktop/xaml-services/types-for-primitives

  3. https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/wpf-xaml-extensions?view=netframeworkdesktop-4.8

[WPF]标记扩展(Markup Extension)的更多相关文章

  1. XAML实例教程系列 - 标记扩展(Markup Extensions) 六

    XAML实例教程系列 - 标记扩展(Markup Extensions) 分类: Windows 8 Silverlight2012-06-21 13:00 1139人阅读 评论(0) 收藏 举报 扩 ...

  2. WPF整理-自定义一个扩展标记(custom markup extension)

    "Markup extensions are used to extend the capabilities of XAML, by providing declarativeoperati ...

  3. 2.6 wpf标记扩展

    1.什么是标记扩展?为什么要有标记扩展? 标记扩展是扩展xmal的表达能力 为了克服现存的类型转换机制存在的 常用的标记扩展有如下: x:Array 代表一个.net数组,它的子元素都是数组元素.它必 ...

  4. [No000012C]WPF(4/7)类型转换器和标记扩展[译]

    介绍 之前讨论了WPF的基础架构,然后逐步开始学习布局面板,转换,介绍了不同的控件,容器,UI转换等.在这篇文章中,我将讨论每个创建XAML应用前的开发人员应该了解的关于XAML最重要的东西. 标记扩 ...

  5. WPF,Silverlight与XAML读书笔记(3) - 标记扩展

    hystar的.Net世界 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 103  文章- 0  评论- 107  WPF,Silverlight与XAML读书笔记(3) - 标记扩展   说 ...

  6. [No0000130]WPF 4.5使用标记扩展订阅事件

    自从我上次写到关于标记扩展的时候已经有一段时间了...... Visual Studio 11 Developer Preview的发布给WPF带来了一些新功能,让我有理由再次使用它们.我要在这里讨论 ...

  7. wpf中xaml的类型转换器与标记扩展

    原文:wpf中xaml的类型转换器与标记扩展 这篇来讲wpf控件属性的类型转换器 类型转换器 类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是可以由xaml组成的,所以标签的便利也需 ...

  8. 标记扩展和 WPF XAML

      本主题介绍 XAML 的标记扩展概念,包括其语法规则.用途以及底层的类对象模型. 标记扩展是 XAML 语言以及 XAML 服务的 .NET 实现的常规功能. 本主题专门详细论述了用于 WPF X ...

  9. WPF:实现自定义标记扩展

    标记扩展使用{标记扩展类 参数}语法,如: <TextBlock Text={x:Null}/> 为什么x:Null就可以返回一个null值呢? 其实在System.Windows.Mar ...

  10. 2019-4-10-win10-uwp-自定义标记扩展

    title author date CreateTime categories win10 uwp 自定义标记扩展 lindexi 2019-04-10 09:46:13 +0800 2019-04- ...

随机推荐

  1. study the docker network of macvlan

    Introduce: 在 Macvlan 出现之前,我们只能为一块以太网卡添加多个 IP 地址,却不能添加多个 MAC 地址,因为 MAC 地址正是通过其全球唯一性来标识一块以太网卡的,即便你使用了创 ...

  2. VBA与VB的区别

    从语言结构上讲,VBA是VB的一个子集,它们的语法结构是一样的.两者的开发环境也几乎相同.但是,VB是独立的开发工具,它不需要依附于任何其他应用程序,它有自己完全独立的工作环境和编译.链接系统.VBA ...

  3. [selenium]相对定位器

    前言 Relative Locators,相对定位器,是Selenium 4引入的一个新的定位器,相对定位器根据源点元素去定位相对位置的其它元素. 相对定位方法其实是基于JavaScript的 get ...

  4. XSS--labs通关记录

    XSS--labs通关记录 level 1(无过滤) 查看网页源代码 <!DOCTYPE html><!--STATUS OK--><html> <head& ...

  5. 转 致创业者:APP已死 服务永生

    前几日,有位创业者和我讲他在带领团队做一个将爱踢球的人集中在一起的App,我告诉他你的创业方向错了.原因在于你的目的是要为爱踢球的人提供服务,而你现在却在竭尽全力的做App,你应该做的是设计你为爱踢球 ...

  6. 【腾讯云 Cloud Studio 实战训练营】在线 IDE 编写 canvas 转换黑白风格头像

    关于 Cloud Studio Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站.用户在使用Cloud Studio 时无需安装,随时随地打开浏 ...

  7. CF1787E The Harmonization of XOR 题解

    CF1787E The Harmonization of XOR 题目大意 给定 \(n\) 个数 \([1, 2, 3, \cdots, n]\) 和两个正整数 \(k\) 和 \(x\). 将这些 ...

  8. 部署属于自己的New bing Ai

    该项目来源 https://github.com/adams549659584/go-proxy-bingai 项目体验地址 https://bing.vcanbb.top/web/#/ 项目介绍 基 ...

  9. 行行AI人才直播第16期:【无界AI首席研究员】刘秋衫《AI创新设计:AIGC赋能设计行业的新思维》

    在这一轮生成式AI浪潮中,设计行业是受波及最为广泛的一个行业.这是设计师们始料未及的事情,至少在此之前,人们认为以设计.艺术为首的创意产业是最难被AI改变的产业之一.而生成式AI的出现,与其说是一次冲 ...

  10. pythonapi接口怎么对接?

    ​ Python API接口对接是使用Python语言开发应用程序时,与外部API接口进行交互的一种方式.API(应用程序接口)是一种定义了程序或系统如何与另一个程序或系统进行交互的协议.通过使用Py ...