Xmal

xmal 中每个元素对应net中的一个类的实例。一般情况下,一个标签对应一个元素。

元素可以嵌套,表示类包含一个类

类有属性,所以元素也需要设置属性,这个通过特性来设置。如果特性不足以完成属性设置,需要通过特殊语法使用嵌套标签。

如上图

1.该xaml文档包括两个元素,因为只有Window 和Grid标签。其中Window的顶级元素,一个xaml只能有一个顶级元素。

顶级元素有Window,page,application

2.上述例子中,在Window的开始标签里有7个特性:分别是一个类,三个名称空间,还有三个属性。

其中三个Window属性,我们上面说了,元素的属性用特性来定义,所以这三个特性是表示Window的属性的。

另外三个名称空间,其中第一个是wpf核心名称空间,包含了所有Wpf类,包括用户界面的控件。这个名称空间

没有加前缀,所以是整个xaml文档的默认名称空间,除非另行指明,则每个元素自动位于这个名称空间下。

有一个前缀为x的名称空间,他是Xaml名称空间,他包含了各自Xaml的实用特性。

(是Xaml语言的相关特性,是语言层面上的特性,而第一个没有前缀的名称空间是表示wpf层面的,是两个不同层面的特性)

这就说明xaml元素对应net的类,xaml的特性要大于net类的属性。上面就是例子,只有三个特性是窗体类的属性,其他几个特性,要不是名称空间,要不是xml的解析规则。

若要使用Xaml的相关特性,需要在元素前面加x。

另外一个名称空间先不说。

还有一个特性是x:class这个表示该class是Xaml名称空间中的特性。这个class告诉Xaml解析器用指定的名称(就是class特性的内容,=后面的字符串)

创建一个类,该类继承自 由xml元素命名的类(也就是包含该特性的元素,本例中是window)。也就是说,创建了一个名叫window1的类,该类继承自window类。

也就是当XAML解析器将包含X:Class特性的Xaml解析成类以后,这个类叫什么,这个类继承自拥有这个标签的元素所对应的类。

 所以window1类时编译时自动生成的,但是只有界面没有逻辑的话,窗口是没有用的,所以我们需要提供部分类,包括事件处理那部分的内容。

这个正式C#语言的的partial class特征实现的。在编译过的程序集中吧这些独立的部分融合到一起。

vs会自动为我们创建这部分类。

window1的隐藏代码类中包含一个无参构造函数,该函数调用了InitializeComponent方法,这个方法非常重要,必须有。

这个方法调用了LoadComponent方法,从程序集中提取BAML(编译过的XAML),并用他来构建用户界面,

解析BAML时,创建每个空间对象,设置其属性,并关联所有事件处理程序

命名元素

命名元素有两种方法。

一种使用XAML的Name特性 即x:Name=“”

一种是不用XAML特性,直接写Name=“”

这两种方法不同,但是结果相同。

第一种是XAML语言的一部分。和wpf类无关。第二种是WPF类中使用了RuntimeNameProperty特性修饰之后,可以使用Name特性

而FrameworkElement类使用了这个特性,并且所有WPF的类都继承自这个类。所以可以使用Name特性。

两个的区别在这里:一个是XAML语言的特性,即XAML语言部分。一个是WPF类的特性,即WPF部分。

 

XAML中的属性和事件

Xam中元素的属性是通过特性来设置的

1.为对象属性赋值

分为两种情况:

1)使用字符串进行简单赋值。这种情况类的属性与xaml的特性可以一一对应,只需要为类的属性做好正确的类型转换。因为xaml的特性是有字符串,而类的属性有很多类型。

2)使用属性元素进行复杂赋值。因为特性的值是一个字符串,复杂程度有限,而类的属性的复杂程度可以是好几层的其他类,如果采用特殊格式的字符串为之赋值,就太头疼了。

为了解决第一种赋值的问题,可以看下面的列子

 

 

 

 

 

 

缺少TypeConverter,引发了错误,所以需要手动写一个

 

 

 

 

 

 写完再类上面加上特性

 

 

 成功给属性赋值。

通过上面例子,我们知道,wpf的特性给属性赋值,在内部写好了转换器,当赋值时,先查找属性有没有

Typeconvert特性,如果没有再查找属性的数据类型的那个类有没有Typeconvert特性,在这个例子中就是

staff对象的person属性,因为person属性本身没有类型转换特性,所以查找到person属性的类型,person类

具有特性。所以转换成功。

 第二种情况是,有的类的属性是另外一个对象,而这个对象又有自己的属性。这样如果也用上面的方法,也

可以,就是需要创建一定格式的字符串,以供类型转换器来转换成对应的类的对象。但是这种方法很复杂,编程

复杂,而且对于格式的要求过于繁杂,容易出错。所以采用了元素属性。

顾名思义,属性是一个元素,这个元素是包含在父标签的内容中的。所以他是父元素的子元素。而他又是父元素

的属性,所以叫做元素属性。

 

 

上面两种为属性赋值的方式都是新生成一个对象,也就是写死了属性值。而在实际应用中,有可能需要用已有的对象,

赋值给多个属性,也有可能将摸个元素的属性赋值给另外一个元素的属性。也有可能将属性赋值为null。这就是上面两种

方式无法实现的。

因此有了扩展标记

 

 

如图,扩展标记用花括号表示,扩展标记也是一个对象,他的类型是左边花括号紧邻的类型,上图的例子就是xaml名称空间中的static类型。

类实例化为对象时,会将类型右边的字符串传入构造函数,给对象属性赋值。

也就是

当编译器看到花括号时

1.会将花括号实例化为一个对象

2.对象的类型时左花括号紧邻的字符串

3.对象的属性由含有逗号的一串字符串负责初始化。

可见标记扩展使用非常方便,但是并不是所有对象都可以使用标记扩展。

标记扩展类继承自   System.Windows.Markup.MarkupExtension。这个类提供了一个

 

 ProvideValue,这个方法返回所需要的的类型。

具体过程是,当编译器遇到上面的x:static时,会创建ataticExtension类,会调用构造函数,并且将字符串传入构造函数中,然后检查标记扩展的等号左边

的属性Foreground的类型,然后发现是Brush,最后调用ProvideValue方法,返回Brush对象,并赋值给Foreground。

 

posted @ 2020-10-28 12:23  小甲点点  阅读(1185)  评论(0编辑  收藏  举报