X名称空间详解

x名称空间映射的是http://schemas.microsoft.com/winfx/2006/xaml。与C#语言一样,XAML也有自己的编译器。XAML语言会被解析并编译,最终形成微软中间语言存储在程序集中。X名称空间作用是与XAML解析编译相关。
X名称空间中常用的内容
从上图看出,X名称空间分为Attribute、标记扩展和XAML指令元素三类。下面分别说一说它们的功能。
4.2.1 x:Class
在这里插入图片描述

这个Attribute的作用是告诉XAML编译器将XAML标签的编译结果(如上图,编译结果为生成一个名为MainWindow的分部类)与后台代码中指定的类合并(如果这个后台类名称也是MainWindow,且也是分部类,则合并)。在使用x:Class时必须遵循以下要求:
● 这个Attribute只能用于根结点。
● 使用x:Class的根结点的类型要与x:Class的值所指示的类型保持一致。
● x:Class的值所指示的类型在声明时必须使用partial关键字。
需要注意的是,后台C#代码中的InitializeComponent()函数是XAML生成的。

4.2.2 x:ClassModifier
这个Attribute的作用是告诉XAML编译器由标签编译生成的类具有怎样的访问控制级别。即设置由XAML生成的类的访问级别。
注意
使用这个Attribute时需要注意:
● 标签必须具有x:Class Attribute。
● x:ClassModifier的值必须与x:Class所指示类的访问控制级别一致。即XMAL对应的C#后台代码类必须与XAML生成的类访问级别一致。XAML生成的类访问级别默认是public。
● x:ClassModifier的值随后台代码的编译语言不同而有所不同,参见TypeAttributes枚举类型。

4.2.3 x:Name
XAML是一种声明式语言,一个标签就表示声明的一个对象(即 new 了一个实例),但这个并没有为这个实例声明一个引用变量,来引用这个实例。而x:Name作用就是为这个实例声明一个引用变量,来引用这个实例。

x:Name的作用有两个:
(1)告诉XAML编译器,当一个标签带有x:Name时除了为这个标签生成对应实例外还要为这个实例声明一个引用变量,变量名就是x:Name的值。
(2)将XAML标签所对应对象的Name属性(如果有)也设为x:Name的值,并把这个值注册到UI树上,以方便查找。

4.2.4 x:FieldModifier
使用x:Name后,XAML标签对应的实例就具有了自己的引用变量,而且这些引用变量都是类的字段。既然是类的字段就免不了要关注一下它们的访问级别。默认情况下,这些字段的访问级别按照面向对象的封装原则被设置成了internal。
注意
因为x:FieldModifier是用来改变引用变量访问级别的,所以使用x:FieldModifier的前提是这个标签同时也使用x:Name,不然何来的引用变量呢?
4.2.5 x:Key
最自然的检索方式莫过于使用“Key-Value”对的形式了。在XAML文件中,我们可以把很多需要多次使用的内容提取出来放在资源字典(Resource Dictionary)里,需要使用这个资源的时候就用它的Key把它检索出来。
**x:Key的作用就是为资源贴上用于检索的索引。**在WPF中,几乎每个元素都有自己的Resources属性,这个属性是个“Key-Value”式的集合,只要把元素放进这个集合,这个元素就成为资源字典中的一个条目,当然,为了能够检索到这个条件,就必须为它添加x:Key。资源(Resources)在WPF中非常重要,需要重复使用的XAML内容,如Style、各种Template和动画等都需要放在资源里,我们将在后面的章节详细讨论。
在XAML中使用资源。
在这里插入图片描述
为了在XAML中使用String类,我们用xmlns:sys="clr-namespace:System;assembly=mscorlib"引用了mscorlib.dll,并把其中的System名称空间映射为XAML中的sys名称空间。然后,我们使用属性标签语法向Window.Resources里添加了一个字符串,并把它的x:Key设置为myString。使用标记扩展 静态资源方式 为第一个TextBox Text属性赋值。

资源不但可以在XAML中访问,在C#中也可以访问。下面是Button.Click的事件处理器:
在这里插入图片描述

4.2.6 x:Shared
在学习x:Key时我们已经知道,一旦我们把某些对象当作资源放进资源字典里后就可以把它们检索出来重复使用。那么,每当它们检索到一个对象时,我们得到的究竟是同一个对象呢,还是这个对象的多个副本呢?这就要看我们给x:Shared赋什么值了。x:Shared一定要与x:Key配合使用如果x:Shared的值为true,那么每次检索到这个对象时,我们得到的都是同一个对象,否则如果x:Shared的值为false,每次我们检索到这个对象时,我们得到的都是这个对象的一个新副本XAML编译器会为资源隐藏地添加x:Shared=“true”,也就是说,默认情况下我们得到的都是同一个对象。
以下是x:Shared=true:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点击改变颜色按钮会发现三个控件的颜色一同改变成绿色。这是因为x:Shared=true,三个控件共用一个SolidBrush对象。
当x:Shared=false时,点击改变颜色按钮会发现只有txt1颜色改变了,此时三个控件各自有各自的SolidBrush对象。
在这里插入图片描述
4.3 x名称空间中的标记扩展
从前面的章节我们已经知道,标记扩展(Markup Extension)实际上就是一些MarkupExtension类的直接或间接派生类。x名称空间中就包含有一些这样的类,所以常称它们为x名称空间内的标记扩展。让我们近观一下那些常用的标记扩展。
4.3.1 x:Type:作用是在XAML中为Type类型数据赋值
顾名思义,x:Type的值应该是一个数据类型的名称。一般情况下,我们在编程中操作的是数据类型的实例或者是实例的引用,但有时候我们也会用到数据类型本身。
初学者往往搞不清数据类型与类、结构、枚举这些名词之间的关系。在此,我来澄清一下。我们拿类(Class)来做分析。就“类”这个名词而言,它是具有双重身份的:在逻辑层面上,类是现实世界对象经过抽象和封装后的结果;在编程层面上,我们会使用这个类去创建对象和引用。当我们使用一个类去创建对象的时候,编译器会以这个类为蓝本、按照类的成员的多寡在内存中开辟出相应大小的一块内存,并用程序员指定的构造器刷新(即初始化)这块内存。这时候,类所充当的角色就是对象的“模具”,使用它创建出来的对象在型号(即内存大小)和内部布局上都完全一样。在这个层面上,我们把类称为数据类型(Type),其实,Type这个词本身就具有型号的意思。以此类推,结构、枚举等也都是数据类型。同时,为了能让程序员在编程层面上自由地操作这些数据类型,比如在不知道具体数据类型的情况下创建这个类型的实例并尝试调用它的方法,.NET Framework中还包含了名为Type的类作为所有数据类型在编程层面上的抽象。
**当我们在XAML中想表达某个数据类型时就需要使用x:Type标记扩展。**比如某个类的一个属性,它的值要求是一种数据类型,当我们在XAML为这个属性赋值时就要使用x:Type。看下面这个例子:
在这里插入图片描述
这个类具有一个Type类型的属性,即UserWindowType,你需要把一种数据类型当作值赋给它。同时,这个类还重写了基类的OnClick方法——除了可以像基类那样触发Click事件外,还会使用UserWindowType所存储的类型创建一个实例,如果这个实例是Window类(或其派生类)的实例,那么就把这个窗体显示出来。
然后,在项目里添加了一个名为MyWindow的Window派生类。它的UI包含三个TextBox和一个Button,背景为浅蓝色:
在这里插入图片描述
最后,把自定义按钮添加到主窗口的界面上,并把MyWindow作为一种数据类型赋值给MyButton.UserWindowType属性:
在这里插入图片描述注意
因为MyButton和MyWindow这两个自定义类都包含在当前项目的名称空间里,所以把当前项目的名称空间引用进来并用local前缀映射:xmlns:local=“clr-namespace:WpfApplication1”。在使用MyButton和MyWindow时也要为它们加上local前缀。
回顾一下标记扩展的语法,因为TypeExtension类的构造器可以接受数据类型名作为参数,所以我们完全可以这样写:
在这里插入图片描述
编译并运行程序,单击主窗体上的按钮,自定义窗体就会显示出来,如图4-6所示。我们还可以多写几个自定义窗体类来扩展这个程序,到时候只需要在XAML里更换UserWindowType的值就可以了。
在这里插入图片描述
4.3.2 x:Null
在XAML中,有时候我们需要显式地对一个属性赋一个空值。在C#语言里,使用null关键字来表示空值,在XAML里用来表示空值的是x:Null。让我们来看一个例子。
大多数时候我们不用显式地为一个属性赋null值,但如果一个属性具有默认值而我们又不需要这个默认值时就需要显式地设置null值了。在WPF中,Style的作用是按照一定的审美规格设置控件的各个属性,程序员可以通过为控件更换Style来产生各种风格迥异的效果。程序员可以逐个为控件设置Style,也可以为一个Style指定目标控件类型,一旦指定了目标类型那么这类控件的实例将都使用这个Style——除非你显式地将某个实例的Style属性设置为x:Null。
在这里插入图片描述
上面的例子把一个Style放在了Window的资源里并把它的x:Key和TargetType都设置成了Button类型,这样,UI上的所有Button控件都会默认地被套用这个Style——除了最后一个Button——因为它显式地把Style设置为了x:Null。
修改代码也可以得到相同的结果:
在这里插入图片描述
4.3.3 标记扩展实例的两种声明语法
前面我们已经认识了x:Type和x:Null两个标记扩展,并使用了它们的
转义字符串式声明
即使用花括号括起来的字符串作为值赋给标签Attribute的形式)。因为标记扩展也是标准的.NET类,所以,我们也可以使用XAML标签来声明标记扩展的实例。拿上面x:Null的例子来说,最后一个Button的代码完全可以写成这样:
在这里插入图片描述
这样做的缺点显而易见,就是代码太啰嗦。所以,为了保持代码的简洁,我们很少使用这种语法。但有一个例外,那就是x:Array标记扩展——如果想在XAML文档里声明一个包含数据的x:Array实例,必须使用标签式声明才能做到。
4.3.4 x:Array
**x:Array的作用就是通过它的Items属性向使用者暴露一个类型已知的ArrayList实例,ArrayList内成员的类型由x:Array的Type指明。**下面这个例子是把一个x:Array当作数据源向一个ListBox提供数据。
在WPF中把包含数据的对象称为数据源(Data Source)。如果想把一个x:Array的实例作为数据源提供给一个ListBox的话,代码是这样:
在这里插入图片描述
此时,作为数据源的x:Array实例是没有数据可提供的,所以需要我们为x:Array实例添加一些数据。这时问题就出现了:向ArrayExtension中添加数据需要调用它的AddChild方法,而在XAML中我们无法编写逻辑代码。同时,ArrayExtension的Items属性是只读的,所以,我们也不可能使用ItemsSource="{x:Array Type=sys:String Items=XXXXXX}"的形式为其赋值。我们只能改用标签声明语法:
在这里插入图片描述
这样,在解析<x:Array>标签的时候编译器会生成调用AddChild方法的代码把<x:Array>标签的子元素逐个添加到x:Array实例的Items里。运行程序,效果如图4-8所示。
在这里插入图片描述
最后,让我们看一下ArrayExtension的源代码片断:
在这里插入图片描述
在这里插入图片描述
4.3.5 x:Static
**x:Static是一个很常用的标记扩展,它的功能是在XAML文档中使用数据类型的static成员。因为XAML不能编写逻辑代码,所以使用x:Static访问的static成员一定是数据类型的属性或字段。**我们看一个例子:
首先,为Window1添加两个static成员,一个是static字段,一个是static属性。
在这里插入图片描述
然后,在XAML中使用x:Static来访问这两个成员:
在这里插入图片描述
运行程序,看到的结果如图4-9所示。
在这里插入图片描述
如果一个程序需要国际化支持,一般会把需要显示的字符串保存在一个资源类的static属性中,所以支持国际化的程序UI中对x:Static的使用非常频繁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值