标记扩展其实就是MarkupExtension类的直接或间接派生类。
x命名空间中就包含一些这样的类,也被称为x命名空间内的标记扩展。
1、x:Type
其值是一个数据类型的名称,一般情况下,编程中操作的嗾使数据类型的实例或实例的引用,但有时也会用到数据类型本身。Type包含在.Net Framework中,用于让程序员在编程层面上自由地操作这些数据类型,尤其是在不知道具体数据类型的情况下创建这个类型的实例并尝试调用它的方法。
在XAML中,想表达某个数据类型时就是用x:Type标记扩展,比如某个类的一个属性,其值要求是一种数据类型,在xaml中为这个属性赋值时就要使用x:Type。
新建一个WPF界面
<Window x:Class="WPF_XAML_2.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MyWindow" Height="170" Width="200"> <StackPanel Background="LightBlue"> <TextBox Margin="5"/> <TextBox Margin="5"/> <TextBox Margin="5"/> <Button Height="30" Width="200" Content="OK"/> </StackPanel> </Window>
创建一个Button的派生类
class MyButton:Button { public Type UserWindowType { get; set; } protected override void OnClick() { base.OnClick(); Window win = Activator.CreateInstance(this.UserWindowType) as Window; if (win != null) { win.ShowDialog(); } } }
这个类具有一个Type类型的属性,即UserWindowType,可以把一种数据类型当做值赋给它,同事这个类还重写了积累的OnClick方法-除了可以像积累那样触发Click事件外,还会使用UserWindowType所存储的类型创建一个实例,如果这个实例时Window类的实例,就会把这个窗体显示出来(ShowDialog)。
然后把自定义按钮添加到主窗体上:
<Window x:Class="WPF_XAML_2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WPF_XAML_2" Title="MainWindow" Height="300" Width="300"> <StackPanel> <local:MyButton Content="Show" UserWindowType="{x:Type TypeName=local:MyWindow}" Margin="5"/> </StackPanel> </Window>
这里MyButton和MyWindow两个自定义类都包含在当前项目的命名空间中,所以把当前项目的命名空间引用进来并使用local前缀映射,使用MyButton和MyWindow时也要为他们加上local前缀。
2、x:Null
有时候需要显式地为一个属性赋一个空值,在C#中,使用Null关键字来标识空值。而xaml中,空值是x:Null。一般不会显式设置Null值,除非不想使用某个属性的默认值时。
<Window.Resources> <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}"> <Setter Property="Width" Value="60"/> <Setter Property="Height" Value="36"/> <Setter Property="Margin" Value="5"/> </Style> </Window.Resources> <StackPanel> <local:MyButton Content="Show" UserWindowType="{x:Type TypeName=local:MyWindow}" Margin="5"/> <Button Content="Ok"></Button> <Button Content="Ok" Style="{x:Null}"></Button> </StackPanel>
上面的示例中把一个Style放到了Window的资源里并把它的x:key和TargetType都设置成了Button类型。这样UI上所有的Button控件都会默认地被套用这个Style,除了最后一个设置为x:Null。
标记扩展实例的两种声明语法:
第一种
<Button Content="OK">
<Button.Style>
<x:Null/>
</Button.Style>
</Button>
这种方式和上面{x:Null}是一个作用,但很啰嗦,一般不会这么使用,除了x:Array标记扩展。
2、x:Array
x:Array的作用是通过它的Items属性向使用者暴露一个类型已知的ArrayList实例,ArrayList内成员的类型由x:Array的Type指明。但因为ArrayExtensions中添加数据需要调用其AddChild方法,而在xaml中无法编写逻辑代码,同时ArrayExtensions的item属性是只读的,所以也不可能使用ItemSource="{x:Array Type=sys:String Items=xxx}"的形式为其赋值,只能改为标签语法:
<ListBox.ItemsSource> <x:Array Type="sys:String"> <sys:String>Tim</sys:String> <sys:String>Tom</sys:String> <sys:String>victor</sys:String> </x:Array> </ListBox.ItemsSource> </ListBox>
3、x:Static
x:Static是一个很常用的标记扩展,功能是在XAML文档中使用数据类型的static成员,因为xaml不能编写逻辑代码,所以使用x:Static访问的一定是数据类型的属性或字段。x:Static多用于国际化。
<Window x:Class="WPF_XAML_3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:WPF_XAML_3" Title="{x:Static local:MainWindow.Place}" Height="350" Width="525"> <Grid Background="LightBlue"> <ListBox Margin="5"> <ListBox.ItemsSource> <x:Array Type="sys:String"> <sys:String>Tim</sys:String> <sys:String>Tom</sys:String> <sys:String>victor</sys:String> </x:Array> </ListBox.ItemsSource> </ListBox> <TextBox FontSize="32" Text="{x:Static local:MainWindow.Place}"/> </Grid> </Window>
4、xaml指令元素
x:code用于在xaml中引入代码块,很少使用。
x:XData
WPF中把包含数据的对象称为数据源,用于把数据源中的数据提供给数据使用者的对象被称为数据提供者(Data Provider)。例如XmlDataProvider,就专门用于提供xml化的数据,如果想在XAML里声明一个带有数据的XmlDataProvider实例,那么XmlDataProvider实例的数据就要放在x:XData标签的内容里。
<Window.Resources> <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books"> <x:XData> <Supermarket xmlns=""> <Fruits> <Fruit Name="Peach"/> <Fruit Name="Banana"/> <Fruit Name="Orange"/> </Fruits> <Drinks> <Drink Name="Coca cola"/> <Drink Name="Pepsi"/> </Drinks> </Supermarket> </x:XData> </XmlDataProvider> </Window.Resources>