WPF笔记(一)之初识XAML
WPF笔记(一)之初识XMAL
本人对Java更熟悉,所以写的时候会不自觉与Java对比
XAML原理
XAML是XML的扩展,在WPF中XAML用于绘制UI,可以理解为用XAML去定义C#的UI类,在XAML中声明了一个标签,就意味着创建了一个对象。
比如WPF项目刚创建好时,XAML为
上面例子中有<Window>
和<Grid>
两个标签,就意味着创建了System.Windows.Window
和System.Windows.Controls.Grid
的对象,然后<Window>
标签上定义了一些属性。
一般来讲,XAML中的属性叫Attribute,对象中的属性叫Property,对象中声明的私有变量叫字段field。Java中没有属性,而是使用Get/Set方法进行了代替。
然后是标签的属性,一行一行来说。
首先是Title、Height、Width这一行,对应Window对象的标题和大小,不再多说。
然后是xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
,其中xmlns
指的是名称空间,代表引用哪些名称空间。这里值看似是一个网址,其实是硬编码到XAML编译器中的,XAML解析时看到这个网址的名称空间就会自动把一些UI相关程序集和名称空间引入进来。
接着是xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
这里xmlns:x
加了一个x
的区分,用来表示不同名称空间,加了区分之后,使用这个名称空间的内容时就需要把区分作为前缀添加的标签上。这一行引用的名称空间里面主要是一些XAML解析需要的程序集。
然后是x:Class
这一行,代表在MyWpfApp命名空间中创建一个MainWindow的类,和MainWindow.xml.cs中的MainWindow是同一个类,继承自Window。
可以在MainWindow.xml.cs中看到MainWindow使用了partial来声明,这个关键字用来在不同文件中声明同一个类,Java中没有这个功能
了解上面的信息之后,对一个最简单的XAML程序的结构就清楚了。
XAML语法基础
XAML中有两种方法给对象的属性赋值:
- 使用字符串进行简单赋值
- 使用元素属性(Property Element)进行复杂赋值
使用简单字符串进行赋值的例子:
这是一个矩形的控件,其中有一个Fill属性用来填充内部的颜色,Rectangle类的Fill属性是Brush类型,Brush的子类很多,比如SolidColorBrush:单色笔刷。所以上面的属性Fill="Blue"
就相当于下面的C#代码
可以看到Blue
这个字符串最终被翻译成了一个SolidColorBrush对象,并赋值给了rectangle。
那么为什么是SolidColorBrush而不是其他Brush子类呢?并且如果要设置的对象比较复杂的时候,字符串不就很复杂、很难写了吗?
使用TypeConverter类将XAML中的Attribute转换为对象的Property
对于第一个问题,字符串如何解析的逻辑由TypeConvert决定。
举个例子,现在有一个可以在XAML中声明的类Human:
想要在XAML中创建出这个类的对象,并且给Child属性赋值,Child的名字叫“ABC”:
直接这么写是编译不过去的,因为XAML解析器并不知道怎么把字符串转化为Human类型,此时就需要TypeConvert类决定如何转换:
Visual Studio 中重写方法时,直接public override就会有提示(IDEA用多了总想着Ctrl+i、Ctrl+o)
然后在Human类上添加上特性:
这样,XAML解析器就知道怎么把“ABC”这个字符串转化为Human对象,然后赋值给Child属性了。
C#中类上面被中括号包起来的叫特性,类似Java中的注解
使用属性元素方式进行属性赋值
XAML中,非空标签都有自己的内容(Content),内容中的子级标签都是副标签内容的一个元素(Element),那么属性元素的意思就是把一个元素当做属性。
也就是上面矩形的例子用属性元素改写一下,将会是这样:
<Rectangle.Fill>
标签代表要给Rectangle的Fill属性赋值,赋给的值就是标签括住的内容。
与之前的代码效果完全一致,这种写法主要用来设置属性复杂的对象。
比如给矩形设置一个渐变的颜色
可以看到这样自由度非常高。
标记扩展
大多数的属性赋值都是为属性生成一个新的对象,但是有时候我们需要把一个对象赋值给两个对象的,或者一个对象的属性依赖于其他对象的属性,这时候就要使用啊扩展标记了。
比如这里有一个文本框,以及一个滑动条,想要的效果是吧滑动条的值显示在文本框里:
上面的代码中,Text="{Binding ElementName=slider1, Path=Value, Mode=OneWay}"
就是标记扩展,这是XAML特有的语法:
- 当XAML编程器遇到这句代码时会把花括号的内容解析成相应的对象
- 对象的数据类型是紧邻左花括号的字符串(这里就是Binding)
- 对象的属性由一连串逗号连接的子字符串进行初始化(属性值不再加引号)
这个写法与C#3.0的对象初始化语法非常相似:
几个小点:
标记扩展是可以嵌套的:Text={Binding Source={StaticResource myDataSource}, Path=PersonName}
标记扩展有一些简写语法,例如{Binding Value, ...}
和{Binding Paht=Value, ...}
是等价的,{StaticResource myString, ...}
和{StaticResource ResourceKey=myString, ...}
是等价的。第一种称为固定位置参数,第二种是具名参数。固定位置参数实际上就是类的构造器的位置。
导入程序集
在XAML中引入类库或其他程序集的语法是:
xmlns:映射名="clr-namespace:类库中名称空间名;assembly=类库文件名"
比如MyLibary.dll中有两个名称空间,在XAML中引用是:
xmlns:common="clr-namespace:Common;assembly=MyLibary"
xmlns:controls="clr-namespace:Controls;assembly=MyLibary"
其中:
- xmlns是XAML中用来声明名称空间的属性,是XML namespace的缩写。
xmlns:
后面的映射名是自定义的,所有引用的名称空间都要加上映射名(无映射名的默认名称空间已经被XAML占用)- 引号中的字符串决定引用那个类库的那个名称空间(Visual Studio可以自动提示)。
x名称空间
x:Class
:指定XAML编译成的类与那个类结合(该类必须声明为partial)x:Name
:为XAML中的标签对象创建引用变量(也就是起个名字,接着就可以在xaml.cs的类中使用了)x:FieldModifier
:指定x:Name
的作用域(public或者private之类的)x:Key
:在XAML中,可以把要复用的资源放在资源字典中(Resource Dictionary),然后通过key检索出来进行复用(在XAML对应的文件中也可以使用String str = this.FindResource("aStr") as String;
)。x:Type
:在C#中,Type类类似Java中的Class类,而x:Type
就是专门给这种类型的属性赋值的(有了Type类之后就可以使用反射了)。x:Null
显式的给属性赋Null值(可以去除默认值或者同一赋值时排除个别控件)。x:Array
提供一个List(一般用作静态的DataSource)x:Static
引用静态成员(字段和属性都可以)
举几个例子:
x:Key举例
x:Type举例
首先创建一个被反射的类:
然后创建一个自定义的Button类:
最后在XAML中给属性进行赋值:
x:Array
一个把x:Array作为数据源的ListBox举例
搜了一下关于x:Array
的讲解并不是很多,看这个介绍好像用起来也不是特别方便,估计一般用来在XAML中写一些静态的值
x:Static
首先添加一个静态成员:
在XAML中使用:
VS2017中,XAML不能识别第一个字段,但实际运行是有效果的。对C#开发规范来说,字段公开时必须以属性形式,因此不用担心这个问题。