[笔记/简译]XAML揭秘(5)

子对象元素(接上文)

字典

    System.Windows.ResourceDictionaryWPF中经常使用的集合,它实现了System.Collections.IDictionary接口,该接口支持在程序代码中添加、移除和枚举键/值对,当我们需要哈希表的时候就可以使用它。在XAML中,我们可以向任何实现了这个接口的集合中添加键/值对,如下例:

 

<ResourceDictionary

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Color x:Key="1" A="255" R="255" G="255" B="255" />

<Color x:Key="1" A="0" R="0" G="0" B="0" />

</ResourceDictionary>

    定义在二级命名空间x中的Key关键字使得我们可以在每一个Color上附加一个键值(Color并不包含Key属性),因此,下面的C#代码与上面的XAML代码等价:

 

    System.Windows.ResourceDictionary d = new System.Windows.ResourceDictionary();

System.Windows.Media.Color color1 = new System.Windows.Media.Color();

System.Windows.Media.Color color2 = new System.Windows.Media.Color();

color1.A = 255; color1.R = 255; color1.G = 255; color1.B = 255;

color2.A = 0; color1.R = 0; color1.G = 0; color1.B = 0;

d.Add("1", color1);

d.Add("2", color2);

    XAML中由x:Key指定的值,除使用了扩展标记外,总是被当作字符串处理,而不会进行任何类型转换。

 

更多的类型转换

    子对象元素通常是纯文本,如下例:

    <SolidColorBrush>White</SolidColorBrush>

    它等价于

    <SolidColorBrush Color="White" />

    尽管Color不是SolidColorBrush的内容属性,但由于存在将“White”“#FFFFFF”这样的字符串转换为SolidColorBrush的类型转换器,所以第一个代码可以执行。

    类型转换器对XAML的可读性起到了巨大作用,但是它也使得XAML在映射.NET对象实例的时候有一点难以理解。根据之前的介绍的知识,我们不能在XAML中声明一个抽象类的元素,因为它无法被实例化。然而尽管System.Windows.Media.BrushSolidColorBrushGradientBrush以及其它具体画刷的抽象类,我们仍旧可以如下简化的方式来表示上面的含义:

    <Brush>White</Brush>

画刷的类型转换器可以将“White”转换到SolidColorBrush,此处即为使用基类Brush对象引用子类SolidColorBrush对象的情形,因此看起来似乎是构造了抽象类,但实际上不是。

 

XAML的扩展

    由于XAML的目的是和.NET类型系统一同工作,因此我们可以使用任何.NET对象(甚至是通过互操作使用COM对象),当然也包括我们自己定义的。虽然这些对象不一定是和用户界面有关,但是它们必须是说明性友好的,比如一个没有默认构造方法的类将不能直接用于XAML(这样的类就是说明性不友好的)。

    WPF程序集通过标记XmlnsDefinitionAttribute来将.NET命名空间映射到XML命名空间,但对于那些不是专门为XAML设计的,或者那些没有使用这个特性的.NET类型,在XAML中应当如何使用它们呢?下面的例子展示了正确的用法:

例:C#

    System.Collections.Hashtable h = new System.Collections.Hashtable();

h.Add("key1", 7);

h.Add("key2", 23);

    XAML

<collections:Hashtable

       xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"

       xmlns:sys="clr-namespace:System;assembly=mscorlib"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<sys:Int32 x:Key="key1">7</sys:Int32>

<sys:Int32 x:Key="key2">23</sys:Int32>

</collections:Hashtable>

    clr-namespace指令使得我们可以在XAML中直接使用.NET命名空间,后面的assemly仅在该.NET命名空间与XAML文档处于不同程序集时才需要,一般情况下仅需要程序集的简单名称,当然我们也可以使用System.Refection.Assembly.Load方法所支持的规范表示法,该表示法包含了如版本号和/或公钥串等额外的信息。

    上例中,子元素之所以能够以x:Key语法添加到HashTable中,是因为HashTable类和其他一些类已经实现了IDictionary接口。另外,可以使用System.Int32是因为已经存在了将字符串转换到整数的类型转换器。(这与Windows Form中从字符串转换到VS属性网格的类型转换机制是相同的)

 

XAML处理子对象元素的规则

    为了避免上述三种子对象元素的二义性,XAML解析器/编译器在遇到子元素的时候,将会按照下列规则处理:

1.    如果类型实现了IList接口,则为每个子元素调用IList.Add方法;

2.    否则,如果类型实现了IDictionary接口,则为每个子元素调用IDictionary.Add方法,并以x:Key的属性值为键值对的键、以元素的值为键值对的值;

3.    否则,如果父元素支持内容属性(由ContentPropertyAttribute特性标识),且子元素兼容该属性,则将子元素作为该属性的值;

4.    否则,如果子元素是纯文本,且存在将它转换到父类型的类型转换器(且没有在父元素上设置任何属性),则使用类型转换器将子元素转换为父元素;

5.    否则,报错。规则12对应上述集合项,规则3对应上述内容属性,规则4对应上述更多的类型转换

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值