信息
您所需的主题如下所示。但此主题未包含在此库中。

TypeConverter 和 XAML

Silverlight

TypeConverter 类作为 XAML 的 Silverlight 实现的一部分服务于特定目的。 在 XAML 处理器创建运行时对象表示形式时,类型转换器处理 XAML 属性值,并将属性字符串转换为对象值。 如果您编写自定义类,并希望通过 XAML 属性值来设置类实例,一般必须编写自定义 TypeConverter 类,然后对引用您的类型转换器实现的类或属性应用 TypeConverterAttribute

本主题包含以下各节:

当在 XAML 中设置属性值时,该值的初始类型为 String 甚至诸如 Double 的其他基元初始也是针对 XAML 处理器的字符串。 到其他非字符串基元值的转换或者到枚举的已命名成员值的转换相对来说更为直截了当,因为固有的类型转换功能已内置在 XAML 处理器中。 其他情况下则要涉及 TypeConverter,此时 Silverlight 核心类、库类或基于 Silverlight 生成的任何代码需要支持一种方式,以便通过为关联属性 (property) 提供属性(attribute) 值在 XAML 中指定新对象值。

XAML 处理器需要两条信息以处理属性值。 第一条信息是要设置的属性值的类型。 在 XAML 中指定为属性值的任意字符串都必须最终转换为或解析为该属性类型的值。 如果属性类型是基元,则将尝试直接转换该字符串。 如果属性类型是枚举,则使用字符串检查该枚举中的成员。 如果属性类型既不是基元也不是枚举,则所涉及的属性或类型的转换行为必须能够基于转换提供的属性值字符串提供该类型的实例或值。

在某些情况下,类型转换是 Silverlight XAML 处理器中固有的行为。 这种类型转换情形的一个示例是类型为 Point 的值。 Point 的类型转换是 Silverlight XAML 分析行为所固有的,不具有 CLR 特性。 在其他情况下,Silverlight 实现一个 TypeConverter 类,然后实现要使用该类的属性类型或成员。 这种类型转换情形的一个示例是类型为 Nullable<bool> 的值。

TypeConverter 类

如果该值既不是基元类型也不是枚举,不存在固有转换,也不存在标记扩展用法,则在处理 XAML 时,必须存在一些将 String 转换为适当值或新实例的方式。 这就是 TypeConverter 类所起的作用。

注意 说明:

作为类的 TypeConverter 可以具有除 XAML 之外的其他用法;在 .NET Framework 中,TypeConverter 在 XAML 存在之前很早就作为类存在了。 Silverlight 和 WPF XAML 处理器以及一般 XAML 设计都将 TypeConverter 模式用于属性值转换,因为当类型转换涉及字符串源时它是满足转换要求的现有编码模式。

TypeConverter 的 Silverlight 实现出于 XAML 处理目的定义两个与转换为字符串和从字符串转换相关的成员:

其中,最重要的方法是 ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) 此方法将输入的字符串转换为必需的对象类型。

CanConvertFrom(ITypeDescriptorContext, Type) 是当服务查询 TypeConverter 实现的功能时可以使用的支持方法。 必须实现 CanConvertFrom(ITypeDescriptorContext, Type) 以便针对某些情况返回 true,尤其是对于 String 类型。

实现采用 ITypeDescriptorContext 的签名,而非不采用 ITypeDescriptorContext 的签名。 此实现模式与实现 TypeConverter 的 WPF 以及一般 .NET Framework 模式一致,这些是 XAML 处理器将调用的签名,尽管在某些情况下它可能这样做,为 ITypeDescriptorContextCultureInfo 传递固定值。 对于非 ITypeDescriptorContext 签名,您的实现应调用基实现。

Silverlight 5 Beta 不使用 ConvertTo(和 CanConvertTo),因为它不合并本机序列化,该序列化使用类型转换器从 XAML 中进行序列化。 您仍应考虑实现 ConvertTo(和 CanConvertTo),将此作为完成转换器类的更广泛互操作性功能的最佳做法。

以下各节一一介绍这四种虚拟方法,您必须重写这些方法才能为 Silverlight XAML 实现类型转换器。

实现 ConvertFrom

若要将该转换器的 ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) 方法用作支持 XAML 的 TypeConverter 实现,该方法必须接受将字符串作为 value 参数。 如果该字符串的格式有效,而且可以由 TypeConverter 实现进行转换,则返回的对象必须支持强制转换为该属性所预期的类型。 否则,ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) 实现必须返回 null

每个 TypeConverter 实现对于什么构成转换的有效字符串可以有自己的解释。

注意 说明:

请勿使用大括号字符,尤其是 {,其原因是它有可能作为您字符串格式的一个元素。 这些字符保留为标记扩展序列的入口和出口。

实现 CanConvertFrom

您的 CanConvertFrom(ITypeDescriptorContext, Type) 实现应为 String 类型的 sourceType 返回 true,否则遵从基实现。

实现 CanConvertTo 和 ConvertTo

如上文中的“TypeConverter 类”一节所述,Silverlight 不提供 XAML 序列化公开,且不调用保存路径类型转换行为本身。 因此,为了在 Silverlight 中使用,您通常需要为专用 Silverlight 类型转换器做的是:用 Visual Studio 生成的实现覆盖调用基实现的包装。 只要调用它们就会导致转换异常,但 Silverlight 代码不会尝试调用这些方法。 不过,您可以考虑提供一个实现,以使您的类型转换器更加可靠,比如用于非 XAML 用途。

不要依赖 context 中的信息,它可能为 null 如果 contextculturenull,并不会引发异常。 如果 contextculture 的输入值为 Null,则应调用基实现,传递 Null 上下文。 此行为引发更为一致的异常。

culture 在被 Silverlight XAML 分析器调用时始终是 en-us 区域性;因此,如果您正在编写支持 XAML 分析的 TypeConverter,则可以假定此行为。 创建全球化应用程序 主题中对此行为的原因进行了说明。

在处理字符串语法中的分隔符时,更需注意区域性行为。 例如,en-us 区域性中的逗号不能与为某些区域性中的逗号字符指定的小数分隔符用法冲突。 有关更多信息,请参见本主题中的“用于 TypeConverter 实现的最佳做法”一节。

如果您打算对 XAML 支持以外的情况支持类型转换,针对其他区域性值的支持可能很有用。

为了将自定义类型转换器用作自定义类的活动类型转换器,必须对类定义应用 TypeConverterAttribute 通过属性指定的 ConverterTypeName 必须是自定义类型转换器的类型名称。 如果应用了此属性,则当 XAML 处理器处理在属性类型使用您自定义类类型情况下的值时,它可以输入字符串并返回对象实例。 您可以将 TypeConverterAttribute 应用到某个接口,尽管很少这样做,也不由 Silverlight 实现的任何接口来执行。

您还可以基于每个属性提供类型转换器。 不将 TypeConverterAttribute 应用到类定义,而是将其应用到属性定义(是主定义,而不是其中的 get/set 访问器实现)。 属性类型必须与自定义类型转换器处理的类型匹配。 如果应用了此属性,当 XAML 处理器处理该属性的值时,它可以处理输入字符串并返回对象实例。 如果选择使用某个属性类型(在其中无法控制类定义并无法将 TypeConverterAttribute 应用到类),则基于属性类型转换器方法尤其有用。

TypeConverterAttribute 和派生类

如果将 TypeConverterAttribute 应用到某个类,然后从该类派生并使用派生类类型作为特定属性类型,则 TypeConverterAttribute 行为不继承。 必须将另一 TypeConverterAttribute 重新应用到派生类定义或将属性类型更改为基类型。 在确定类型转换器是否可用于某个值时,XAML 分析器查找与声明类型精确匹配的属性类型。 依据 CLR 继承的一般规则,您可以为实际值提供派生类或基类。

TypeConverterAttribute 应用到单个属性而不是它们的目标类型时,即便要从属性所属类型派生(只要原始属性未被隐藏),该属性也将保持转换行为。

通常,为 XAML 实现 TypeConverter 是为了对一个或多个属性提升简化的属性用法。 您可以在大多数常用属性已支持某种属性语法的情况下,为另外一些属性执行上述实现;要求用于新属性的属性元素语法将导致标记极为冗长。

您应在定义 TypeConverter 时考虑到这一点,清楚您是在定义自包含的语法。 务必让您的语法简洁明了,并使用用户可能了解或对用户直观的语法约定。 如果适当进行了属性化,在 Visual Studio 中编辑 XAML 时可以从“属性”窗口调用类型转换。 这有助于引导用户发现您的用法;并且,作为一项属性编辑功能,Visual Studio 将拒绝针对启用类型转换器的属性的无效输入。 某些 Visual Studio 属性方案(如颜色选取器)在可能有的类型转换器语法之外还支持专用的属性编辑器。 但是,生成或编辑 XAML 的其他设计环境不一定具有可帮助用户发现您的类型转换语法的任何提示。 其他设计环境尝试在运行时加载无效的 XAML 时,不一定会拒绝该 XAML;而且运行时 XAML 分析器错误不一定总有助于指示类型转换器用法为何可能无效。

正确的类型转换方案的示例包括这样的情况:用于表示数据在其他标记范例中存在的已有约定,或针对如何以书面文字表示数据的约定。 例如,Point 的类型转换的 X,Y 格式(使用逗号作为 X 和 Y 的分隔符)基于数学中现有的表示约定。 另一个示例情况是:如果您的属性通常支持某种主要数据类型,但同时也支持无法用主要数据类型的字符串表示形式表示的某些特殊值。 这种类型转换方案的一个示例是 Duration,它通常支持 TimeSpan 值(这些值具有自己的时间格式类型转换器),但也支持诸如文本字符串 Forever 之类的特殊值。 对于这种情况,最佳做法是对转换的类型公开一个静态字段或属性。 这样可提供可供代码使用的等效值,而不要求代码用户创建并调用您的类型转换器,并且传递字符串标记文本。 如果 CLR 规则允许,该字段或属性应具有与用作特殊语法信息项的文本相同的名称。

通常,类型转换语法包含不止一个信息项。 在类型转换器所拆分并作为多个部分处理的字符串各原子之间,经常选用逗号作为分隔符。 空格字符也经常用作分隔符,而且许多类型转换器实现都将逗号或空格视为等效的分隔符。

如果定义类型,应尽可能对类型而不是属性应用 TypeConverterAttribute 在下面的情况中不应对属性保留 TypeConverterAttribute

  • 您不是要定义属性目标类型,而是要重新设计该目标类型的用途,以供您的属性 XAML 用法使用。

  • 常用类型用于多个属性,但每个这样的属性都具有不同的验证规则,用于验证哪一个类型的值可作为值受到支持。

  • 您定义类型,但不希望该类型依赖 TypeConverterAttribute 或总体 CLR 属性化所需的 Silverlight 程序集。

不要试图将左大括号 ({) 用作类型转换语法的有效字符。 这会与 XAML 分析器用来标识标记扩展用法的方式产生冲突。

社区附加资源

显示:
© 2014 Microsoft