闲话WPF之七(XAML的向前兼容性)
同样地,我们用一个简单的例子来帮助说明XAML的向前兼容性。假设有一个自定义的CLYLButton,实现了一个Light属性。在V1版本它的默认属性值是Blue(蓝光)。在V2版本中支持属性值Green(绿光)。假设我们在程序中利用Light属性实现了绿光效果。但是,如果恰好目标机器上的V2版本意外地被替换为了V1版本。此时,程序的行为应该怎么样呢?崩溃,不,我们希望它在没有V2的情况下能利用V1版本的默认值实现蓝光效果。如何实现且看XAML标记的向前兼容性。向前兼容性表示通过标记兼容性名字空间的Ignorable属性标识元素、属性和类,使它们可以动态的支持向前版本。
<CLYLButton V2:Light="Green"
xmlns="...assembly-v1-uri..."
xmlns:V2="...assembly-V2-uri..."
xmlns:mc=http://schemas.micrsoft.com/winfx/2006/markup-compatibility
mc:Ignorable="V2" />
这就利用了标记兼容性名字空间的Ignorable属性。mc:Ignorable=”V2”表示所有用V2前缀关联的名字空间中元素或者属性都是可以忽略的。如果现在只有V1版本的CLYLButton,上面的代码就被XAML加载器解释为:
<CLYLButton Light=”Blue” xmlns=”… assembly-V1-uri …”/>
如果现在有V2版本的CLYLButton,上面的代码将被XAML加载器解释为:
<CLYLButton Light=”Green” xmlns=”… assembly-V2-uri …”/>
XMAL标记兼容性除了可应用在属性上,还可以应用在元素之上。仍然通过例子进行说明,定义如下的一个类:
[ContentProperty("Buttons")]
public class CElement {
List<CLYLButton> _buttons = new List<CLYLButton>();
public List<CLYLButton> Buttons { get { return _buttons; }
}
关于ContentProperty的用法可以参考MSDN文档ContentPropertyAttribute Class
同样,我们可以如下编写XAML代码,使其可以同时兼容两个版本的CElement。
<CElement mc:Ignorable="V2"
xmln="...assembly-v1-uri..."
xmlns:V2="...assembly-V2-uri..."
xmlns:mc="http://schemas.micrsoft.com/winfx/2006/markup-compatibility">
<CLYLButton Light="Blue" />
<V2:CLYLButton Light="Green"/>
</CElement>
这样,如果加载器有V2版本,则Green属性值生效。如果没有则被忽略。类似地,我们还可以完全自动地处理名字空间的类:
<CElement mc:Ignorable="v2"
xmln="...assembly-v1-uri..."
xmlns:V2="...assembly-v2-uri..."
xmlns:mc="http://schemas.micrsoft.com/winfx/2006/markup-compatibility">
<V2:Favor/>
</CElement>
加载时,如果没有V2版本存在,Favor类实例同样将被忽略。
在Markup Compatibility中,除了有前面介绍的Comment、Ignorable属性修饰外,另一个有趣的就是AlternateContent。利用AlternateContent,我们能方便的实现可选内容。比如,我们的程序使用了V2版本Assembly的CLYLButton类,但是,如果没有找到这个Assembly,那么它对应的内容自动用另一个指定版本V1替换,而不是兼容性体现的忽略。看下面的例子:
<CElement mc:Ignorable="v2"
xmln="...assembly-v1-uri..."
xmlns:v2="...assembly-v2-uri..."
xmlns:mc="http://schemas.micrsoft.com/winfx/2006/markup-compatibility">
<mc:AlternateContent>
<mc:Choice Requires="V2">
<CLYLButton Light="Green" Shape="Dog" />
<V2:Favor/>
</mc:Choice>
<mc:Fallback>
<CLYLButton Light="Blue"/>
</mc:Fallback>
</mc:AlternateContent>
</CElement>
这一段XAML代码在有V1版本的Assembly时将被视为:
<CElement xmln="...assembly-v1-uri...">
<CLYLButton Light="Blue"/>
</CElement>
如果有V2版本的Assembly,编译的结果如下:
<CElement xmln="...assembly-v1-uri...">
<CLYLButton Light="Green"/>
<Favor/>
</CElement>