该文章针对于《深入浅出WPF》的知识做总结,方便自己回顾。
XAML是什么?“XAML”是WPF中专门用于设计UI的语言,XAML有什么优点呢?
XAML可以设计出专业的UI和动画(好用)
2.XAML不需要专业的编程知识,它简单易学、结构清晰(易学)
3.XAML使设计师能直接参与软件开发,随时沟通、无需二次转化(高效)
4.XAML最大的优点:它让UI和逻辑的剥离。XAML是一种单纯的“声明型语言”它只能用来声明一些UI元素、绘制UI和动画,根本无法在其中加入程序逻辑,这就强制地把逻辑代码从UI代码中赶走了,这样UI的元素统统在UI层,逻辑相关的代码统统都在逻辑层,形成了“高内聚-低耦合”的结构,这样的机构前提底层逻辑相同的情况下,可以大改他的UI界面而不会对后端的逻辑代码有影响。
在新建WPF的项目后,APP.xaml 是程序的主体,它的作用就是声明程序的进程会是谁,同时指定程序的主窗体是谁。
XAML是一种由XML派生而来的语言,所以很多XML中的概念在XAML是通用的,XAML中使用标签声明元素,标签有两种第一种就是有起始标签<>和终止标签>,加在<>和>标签的内XAML代码表示这个标签的内容。如果没有内容,就用第二种标签空标签>。XAML是一种“声明”式语言,当看见应该标签,就意味着声明了一个对象,对象之间的层级关系要么是并列、要么是包含,全都体现在标签的关系上
Attribute(特征) Property(属性)
以上代码就是WIndow标签的Attribute(特征),其中的Title(标题、窗体展示的标题)、Height、Width是Window对象的Property(属性)。
以上代码可以看到"xmlns",它是在声明名称空间,xmlns是“XML-Namespace”的缩写。xmlns特征的语法格式如下
xmlns:映射前缀=“名称空间”
“:映射前缀”也可以不填,如上图的第二个xmlns,这种没有映射前缀的的名称空间称为“默认名称空间”。
xmlns:local= "名称空间"
我们看到的像网址的代码其实是XAML解析器的一个硬性编码。(一般不管!知道是什么东东就可以了,所以别去动他!)
x:Class=" "
x:Class=" "的作用是当XAML解析器将包含它的标签解析成C#,并和C#代码合二为一。因为C#代码的partial机制。
与传统的Winfrom程序思维不同,XAML使用树形逻辑结构来描述UI。这种树形结构对于WPF整体系统都具有非常重要的意义,它是不但影响着UI的布局设计,还深刻地影响着WPF地属性(Property)子系统和事件(Event)。对于相同的页面,可以使用不同的XAML来是实现。
XAML是一种声明性语言,XAML编译器会为每个标签创建一个与之对应地对象。对象创建出来后要对它地属性进行必要地初始化才有使用地意义。XAML中为对象属性赋值共有两种语法。
1、使用字符串进行简单赋值
2、使用属性元素(Property Element)进行复杂赋值
每个代码都有他自己适用的地方,属性元素赋值和字符串赋值比较起来就相对于比较啰嗦。
能使用字符串赋值就别用啰嗦的属性元素赋值,充分利用默认值,去除默认值。
事件处理器与后置代码,小编之前学过winfrom编程,所以对事件和后置代码还是容易理解,WPF和Winfrom的区别 我个人觉得在于UI界面的XAML和WPF是数据驱动界面。
在.NET事件处理机制中,可以为对象的某个事件指定一个能与该事件匹配的成员函数,当这个事件发生时,.NET运行时会调用这个函数,即表示这个事件的相应和处理。因此我们把这个函数称为“事件处理器”。以Button控件为例:
这里C#代码中的 Button_click()函数就是代码后置
由于C#支持partial类,XAML标签又可以使用x:Class特征指定将由XAML代码解析生成的类与哪个类合并,因此我们完全可以把用于实现程序逻辑的C#放在一个文件里,把用于描述程序UI的XAML代码放在另外的文件里,并且让事件性Attribute充当XAML与C#之间沟通的纽带,这种将逻辑代码与UI代码分离、隐藏在UI代码后面的形式叫做“代码后置”
在XAML中的注释和H5一样,
x名称控件映射的是 "http://schemas.microsoft.com/winfx/2006/xaml",它包含的类均与解析XAML语言相关,所以亦称为“XAML名称控件”,和C#语言一样,XAML也有自己的编译器。XAML语言会被解析并编译,最终形成微软中间语言存储在程序集中。在解析和编译XAML语言的过程中,我们经常需要告诉编译器一些重要的信息,比如XAML代码的编译结果应该与哪些C#代码的编译结果合并、声明的元素是声明访问级别等等。这些让程序员能够与XAML编译器沟通的工具存放在x名称空间中,也就是
“xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"”中
x:Class作用是告诉XAML编译器将XAML标签的编译结果与后台代码中指定的类合并
他只能使用与根节点(Window)
它的值所指示的类型在声明时必须使用partial关键字(代码后置的类必须使用partial关键字)
x:ClassModifier的作用是告诉XAML编译由标签编译生成得类具有怎么样的访问控制级别
标签必须具有x:Class 特征
ClassModifier的值必须与x:Class所指示类的访问控制级别一致
x:Name的作用是显式地告诉XAML编译器为这个对象声明引用变量。
x:Name地作用有两个
(1)告诉XAML编译器,当一个标签带有x:Name时除了为这个标签生成对应实例外还要为这个实例声明一个引用变量,变量名就是x:Name的值
(2)将XAML标签所对应对象的Name属性(如果有)也设置为x:Name的值,并把这个值注册到UI树上,以方便查找,如果一个标签对应的实例没有Name这个属性,那么x:Name作用就只剩下为这个实例创建引用变量了。
使用Name 和 x:Name的效果一样,取决于控件是否Name属性,建议直接使用x:Name,代码同意性和可读性更高
x:FieldModifier作用是用来改变引用变量访问级别的,所以使用x:FieldModifier的前提是这个标签同时也使用x:Name。
有时候我们需要从第一个程序集访问另一个程序集中窗体的元素,这时候就需要把被访问控件的引用变量改为public级别。
x:FielModiffier必须和x:Name一起使用
x:Key的作用是为资源贴上用于检索的索引
在WPF中几乎每个元素都有自己的Resources属性,这个属性是“Key-Value”式的集合,只要把元素放进这个集合,这个元素就成为资源字典中的一个条目,为了检索到这个条目,就必须为它加上x:Key。
x:Type当我们在XAML中想表达某个数据类型时就需要使用x:Type标记扩展
x:Null在XAML中用来表示空值
大多数时候我们不用显示地为一个属性赋null值,但如果一个属性具有默认值而我们又不需要这个默认值地时候就需要显示地设置null值了。
x:Array的作用就是通过它的Items属性向使用者暴露一个类型已知的ArrayList实例
在解析
s:Static是一个很常用的标记扩展,它的功能是在XAML文档中使用数据类型的static成员。因为XAML不能编写逻辑代码,所以使用x:Static访问的static成员一定是数据类型的属性或字段。
x:Static说白就是让UI界面的XAML可以调用C#的数据(属性或字段)
x:Code它的作用就是可以包含一些本应放置在代码中的C#代码。这样做的好处是不用把XAML代码和C#代码分置在两个文件中,但这样做个人觉得违背WPF的初衷,把UI代码和逻辑代码写在一起就体现不出来UI和逻辑代码完全分离。所以一般不用,除非遇到某种极端环境。
x:XData标签是一个专用标签。WPF中把包含数据的对象成为数据源,用于把数据源中的数据提供给数据使用者的对象称为数据提供者。
WPF中是数据驱动UI,数据是核心,是主动的;UI从属于数据并表达数据、是被动的。WPF把那些能够展示数据、响应用户操作的UI元素称为控件。控件所展示的数据,我们称为控件的“数据内容”控件在响应用户操作后会执行自己的一些方法或以事件的形式通知应用程序,我们称为控件的“行为”或“算法内容”。
可以把控件想象成一个容器,容器里装的东西就是它的内容。控件的内容可以直接是数据也可以是控件。当控件的内容还是控件的时候就形成了控件的嵌套。我们把被嵌套的控件称为子级控件。因为运行控件嵌套,所以WPF的UI会形成一个树形结构。
控件是内存中的对象,控件的内容也是内存中的对象。控件通过自己的某个属性引用着作为其内容的对象,这个属性称为内容属性。“内容属性”是个统称,具体到每种控件上,内容属性都有自己确切的名字,有的叫Content,有的叫Child;有些控件的内容可以时集合,其内容属性有叫Items或Children的。
ContentControl族
均派生自ContentControl类
它们都是控件(Control)
内容属性的名称为Content
只能由单一元素充当其内容
ContentControl族包含的控件
Button |
ButtonBase |
CheckBox |
ComboxBoxItem |
ContentControl |
Frame |
GridViewColumnHeader |
GroupItem |
Label |
ListBoxItem |
ListViewItem |
NavigationWindow |
RadioButton |
RepeatButton |
ScrollViewer |
StatusBarItem |
ToggleButton |
ToolTip |
UserControl |
Window |
HeaderedContentControl族
它们都派生HeaderedContentControl类,HeaderedContentControl是ContentControl的派生类
它们都是控件,用于显示带标题的数据
除了用于显示主体内容的区域外,控件还具有一个显示标题(Header)的区域
内容属性为Content和Header
无论是Content还是Header都只能容纳一个元素作为其内容。
HeaderedContentControl族包含的控件
Expander |
GroupBox |
HeaderedContentControl |
TabItem |
ItemsControl族
均派生自ItemsControl类
他们都是控件,用于显示列表化的数据
内容属性为Items或ItemsSource
每种ItemsControl都对应自己的条目容器
ItemsControl族包含的控件
Menu |
MenuBase |
ContextMenu |
ComboBox |
ItemsControl |
ListBox |
ListView |
TabControl |
TreeView |
Selector |
StatusBar |
HeaderedIemsControl族
均派生自HeaderItemsControl类
它们都是控件,用于显示列表化的数据,同时可以显示一个标题。
内容属性为Items、ItemsSource和Header
Decorator类
均派生自Decorator类
起UI装饰作用
内容属性为Child
只能由单一元素充当内容
Decorator族元素
ButtonChome |
ClassicBorderDecorator |
ListBoxChrome |
SysatemDropSgadowChrome |
Border |
InkPresenter |
BulletDecorator |
Viewbox |
AdornerDecorator |
TextBlock和TextBox
它俩的作用就是显示文本。TextBlock显示文本但不能编辑,所以又叫静态文本。TextBox则允许用户编辑其中的内容。
Shape族元素
Shape族元素它们只是简单的视觉元素,不是控件,就是专门用来在UI上绘制图形的一类元素。这类元素没有自己的内容,我们可以使用Fill属性为它们设置填充效果,还可以使用Stroke属性为它们设置边线的效果。
均派生自Shape类
用于2D图形绘制
无内容属性
使用Fill属性设置填充,使用Stroke属性设置边线
Panel族元素
均派生自Panel抽象类
主要功能是控制UI布局
内容属性为Children
内容可以是多个元素,Panel元素将控制它们的布局
Panel族元素
Canvas |
DockPanel |
Grid |
TabPanel |
ToolBarOverflowPanel |
StackPanel |
ToolBarPanel |
UniformGrid |
VirtualizingPanel |
VirtualizingStackPanel |
WrapPanel |
UI布局(Layout)
WPF作为专门的用户界面技术,布局功能是它的核心功能之一。友好的用户界面和良好的用户体验离不开设计精良的布局。WPF的布局理念就是把一个布局元素作ContentControl或HeaderContentControl族控件的Content,再在布局元素里添加要被布局的子级控件。
Grid
Grid:网格。可以自定义行和列并通过行列的数值、行高和列宽来调整控件的布局。近似于HTML中的Table。Grid的特点如下:
可以定义任意数量的行和列,非常灵活
行的高度和列的宽度可以使用绝对数值、相对比例或自动调整的方式进行精确设定,并可以设置最大和最小值
内部元素可以设置自己的所在行和列,还可以设置自己纵向跨几行、横向跨几列
可以设置Children元素的对齐方向
Grid类具有ColumnDefinitions(定义多少列)和RowDefinitions(定义多少行)两个属性,如果需要动态地调整Grid地布局,可以在C#完成对列和行地定义。代码如下:
Grid可接受地宽度和高度地单位
英文名称 |
中文名称 |
简写 |
换算 |
Pixel |
像素 |
px(默认) |
图形基本单位 |
Inch |
英寸 |
in |
1inch=96pixel |
Centimeter |
厘米 |
cm |
1cm=(96/2.54)pixel |
Point |
点 |
pt |
1pt=(96/72)pixel |
对于Grid的行高和列宽,我们可以设置三类值
绝对值:double 数值加单位后缀
比例值:double数值后加上一个星号(*) --1*可以简写为*
自动值:字符串Auto
为控件指定行和列遵循以下规则
行和列都是从0开始计数
指定一个控件在某行,就为这个控件的标签添加Grid.Row=“行编号”这样一个特征,若编号为0(即控件处于首行)可以省略不写
指定一个控件在某列,就为此控件添加Grid.Column=“列编号”这样的特征,若编号为0则可以省略不写
若控件需要跨多个行和列,请使用Grid.RowSpan=“行数”和Grid.ColumnSpan="列数"
StackPanel
StackPanel可以把内部元素在纵向或横向上紧凑排列、形成栈式布局,通俗地讲就是把内部元素像垒积木一样。StackPanel使用3个属性来控制内部元素地布局,它们是Orientation、HorizontalAlignment和VerticalAlignment
StackPanel的三个属性
属性 |
可取值 |
描述 |
Orientation |
Horizontal Vertical |
绝对内部元素是横向累积还是纵向累积 |
HorizontalAlignment |
Left Center Right Stretch |
决定内部元素水平方向上的对齐方式 |
VerticalAlignment |
Top Center Bottom Stretch |
决定内部元素竖直方向上的对齐方式 |
Canvas
Canvas翻译过来就是“画布”,显然在Canvas里布局就像画布上画控件一样。当控件被放置在Canvas里时就会被附加上Canvas.X和Canvas.Y属性
Canvas使用的场合包括:
一经设计基本上不会再有改动的小型布局(如图标)
艺术性比较强的布局
需要大量使用横纵坐标进行绝对点定位的布局
依赖于横纵标的动画
DockPanel
DockPanel内的元素可以通过Left、Top、Right、Buttom四个值来指定元素会指定方向累积,DockPanel还有一个重要的属性,bool类型的LastChildFill,它的默认值是True。当LastChildFill属性值为True时,DockPanel内最后一个元素的DockPanel.Dock属性值会被忽略,这个元素会把DockPanel内部所有剩余控件充满。(这个布局控件的Dock和小编之前学的Dock属性用法差不多)
WrapPanel
WrapPanel内部采用的是流式布局。WrapPanel使用Orientation属性来控制流延伸的方向,WrapPanel会排列尽可能多的控件,排不下的控件将会新起一行一列继续排序