XAML和自定义类

Posted X·3

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XAML和自定义类相关的知识,希望对你有一定的参考价值。

XAML和自定义类

可扩展应用程序标记语言(XAML)支持使用任何公共语言运行库(CLR)语言定义自定义类或结构,然后使用XAML标记(包括在同一标记文件中混合使用 Windows Presentation Foundation (WPF)定义的XAML和自定义类的XAML标记)访问该类的功能。本主题讨论自定义类要用作XAML元素时所必须满足的要求。

应用程序或程序集中的自定义类

可以使用两种不同的方法定义XAML中使用的自定义类:在生成主Windows Presentation Foundation (WPF)应用程序的代码隐藏或其他代码中定义,或者在单独的程序集(如用作类库的可执行文件或 DLL)中定义为类。这些方法中的每一种都有特定的优点和缺点。

创建类库的优点是,任何这样的自定义类都可以在许多可能不同的应用程序中共享。单独的类库也使应用程序的版本问题更易控制,而且也简化了在XAML页上创建要用作根元素的类这一过程。

在应用程序中定义自定义类的优点是,此方法是相对轻量的方法,可最大限度减少当引入主可执行文件之外的单独程序集时遇到的部署和测试问题。但是,一个显著的缺点是,不能将同一程序集中定义的类用作XAML页的根元素。

无论是在相同还是不同程序集中定义自定义类,都需要在CLR命名空间和XAML命名空间之间映射这些自定义类才能在XAML中使用它们。

自定义类作为XAML元素的要求

  1. 类要能够实例化为对象元素,必须满足以下要求:
  2. 自定义类必须是公共的且支持默认(无参数)公共构造函数。(托管代码结构隐式支持这样的构造函数。)
  3. 自定义类不能是嵌套类(嵌套类和其语法中的“点”会干扰其他 WPF 功能,例如附加属性)。
  4. 除了启用对象元素语法外,还应对将该对象用作其值类型的任何其他公共属性启用属性元素语法。这是因为,对象现在可以实例化为对象元素,而且可以填充此类属性的属性元素值。

自定义类的属性(Property)作为XAML属性(Attribute)的要求

属性必须引用按值类型(如基元),或者为在类级别具有默认构造函数或专用类型转换器的类型使用类。

或者,属性可以引用抽象类类型或接口。对于抽象类或接口,运行时的期望是,属性值必须使用实现该接口的实际类实例或从该抽象类派生的类实例填充。

属性可以在抽象类上声明,但只能在从抽象类派生的实际类上设置,因为创建类的对象元素完全要求有效的默认构造函数和可实例化的类。

启用了类型转换器的属性语法

如果在类级别提供专用的属性化类型转换器,则应用的类型转换将为任何需要实例化该类型的属性启用属性语法。类型转换器不启用该类型的对象元素用法;只有当存在该类型的默认构造函数时才会启用对象元素用法。所以,启用了类型转换器的属性一般而言在属性语法中不可用,除非该类型本身也支持对象元素语法。这一点的一个例外是,可以指定属性元素语法,但允许该属性元素包含一个字符串。该用法实质上相当于属性语法用法,这样的用法不常见,除非需要对属性值进行更可靠的空白处理。

允许使用属性语法,但通过XAML禁止使用包含对象元素的属性元素语法的属性示例有各种接受Cursor类型的属性。Cursor类有专用类型转换器 CursorConverter,但未公开默认构造函数,因此Cursor属性只能通过属性语法进行设置,即使实际Cursor类型为引用类型。

每个属性类型转换器

此外,属性本身也可以在属性级别声明类型转换器。对于基于适当类型的ConvertFrom操作,通过将属性(attribute)的传入字符串值作为输入进行处理,这将启用“mini language”,它将实例化内联属性(property)类型的对象。通常,这样做是为了提供方便的访问器,而不是作为在 XAML 中设置属性的唯一手段。但是,对于想要使用现有CLR类型(不提供默认构造函数或属性化类型转换器)的属性,也可以使用类型转换器。例如,WPF API中接受CultureInfo类型的某些属性。在此情况下,WPF使用现有的Microsoft .NET Framework CultureInfo类型来更好地处理与早期版本框架的兼容性以及早期版本框架中使用的迁移方案,但CultureInfo类型不支持将必要的构造函数或类型级别的类型转换直接用作XAML属性值。

公开具有XAML用法的属性时,特别当您是控件作者时,尤其应考虑使用依赖项属性支持该属性。使用XAML处理器的现有Windows Presentation Foundation (WPF)实现时更是如此,因为使用DependencyProperty支持可以提高性能。对于用户期望的XAML可访问属性,依赖项属性将公开该属性的属性系统功能。这些功能包括动画、数据绑定和样式支持。

编写和属性化类型转换器

您可能经常需要编写自定义TypeConverter派生类,以便为属性类型提供类型转换。

有关自定义类事件的XAML事件处理程序属性语法的要求

若要将事件用作CLR事件,必须在支持默认构造函数的类上或可以在派生类中访问事件的抽象类上,将该事件公开为公共事件。为了可方便地用作路由事件,CLR事件应实现显式add和remove方法,这两种方法分别添加和移除CLR事件签名的处理程序,并将这些处理程序转发到AddHandler和RemoveHandler方法。这些方法在事件所附加到的实例的路由事件处理程序存储区中添加或删除处理程序。

说明:

可以使用AddHandler直接注册路由事件的处理程序,而不用特意定义用于公开路由事件的CLR事件。通常建议不要这样做,因为该事件不会对附加处理程序启用XAML属性语法,并且所生成的类将为类对象模型提供不够透明的XAML视图。

编写集合属性

接受集合类型的属性具有的XAML语法允许您指定要添加到集合的对象。此语法有两种显著功能。

不需要在对象元素语法中指定属于集合对象的对象。如果在XAML中指定接受集合类型的属性,则隐式存在该集合类型。

该集合属性的子元素将被处理为集合的成员。通常,代码对集合成员的访问通过集合方法(如 Add)或集合索引器属性执行。但XAML语法不支持方法或索引器。对于生成元素树的操作,集合明显是很常见的要求,您需要在声明性XAML中通过某种方法填充这些集合。因此,处理集合属性的子元素的方法是将这些子元素添加到将作为集合属性类型值的集合中。

WPF XAML处理器对集合属性的构成内容使用以下定义。属性的属性类型必须实现以下内容之一:

  1. 实现IList。
  2. 实现IDictionary或等效泛型(IDictionary<(Of <(TKey, TValue>)>))。
  3. 从 Array 派生实现IAddChild(WPF 定义的接口)。
  4. 这每一种类型都具有Add方法,XAML处理器使用该方法向基础集合中添加项。

说明:

由WPF XAML处理器执行的集合检测功能不支持泛型列表和字典接(IList<(Of<(T>)>)和IDictionary<(Of<(TKey,TValue>)>))。但是,可以将List<(Of<(T>)>)类用作基类(因为它直接实现 IList),或者将 Dictionary<(Of <(TKey,TValue>)>)用作基类(因为它直接实现IDictionary)。

声明接受集合的属性时,务必注意在该类型的新实例中初始化属性值的方式。如果未将属性实现为依赖项属性,则使属性使用可调用集合类型构造函数的支持字段是合适的。如果属性是依赖项属性,则可能需要将集合属性初始化为默认类型构造函数的一部分。这是因为依赖项属性从元数据接受其默认值,您通常不会希望集合属性的初始值是静态的共享集合(每个包含类型实例都应有集合实例)。

您可以为集合属性实现自定义集合类型。由于集合属性隐式进行处理,因此自定义集合类型不需要提供默认构造函数就可以在XAML中隐式使用。但是,也可以选择为集合类型提供默认构造函数。这可能是一种值得的做法,因为除非确实提供了默认构造函数,否则不能显式将集合声明为对象元素。一些标记作者可能喜欢将显式集合视作一种标记样式。另外,在创建将集合类型用作属性值的新对象时,默认构造函数可以简化初始化要求。

以上是关于XAML和自定义类的主要内容,如果未能解决你的问题,请参考以下文章

XAML和自定义类

XAML和自定义类

Linux framebuffer驱动和自定义文件操作

Emacs、AUCTeX 和自定义命令的缩进

AspNet.Identity 自定义用户和自定义角色应该很简单;我错过了啥?

React Router v4 baseName 和自定义历史