C#学习(七)之WPF&XAML
这一周章老师又讲解了许多内容,本次学习记录就选取我非常感兴趣且实验需要的重要知识-WPF以及与它紧密联系的XAML进行探究。
首先介绍一下基本知识。
WPF(Windows Presentation Foundation),中文译名“Windows呈现基础”是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。WPF是微软新一代图形系统,运行在.NET Framework 3.0及以上版本下,为用户界面、2D/3D 图形、文档和媒体提供了统一的描述和操作方法。基于DirectX 9/10技术的WPF不仅带来了前所未有的3D界面,而且其图形向量渲染引擎也大大改进了传统的2D界面,比如Vista中的半透明效果的窗体等都得益于WPF。 程序员在WPF的帮助下,要开发出媲美Mac程序的酷炫界面已不再是遥不可及的奢望。 WPF相对于Windows客户端的开发来说,向前跨出了巨大的一步,它提供了超丰富的.NET UI 框架,集成了矢量图形,丰富的流动文字支持(flow text support),3D视觉效果和强大无比的控件模型框架。如下面这些漂亮的应用界面:
在WPF编程中,用户界面实际上完全是由XAML(Extensible Application Markup Language),即“可扩展应用程序标记语言”来编写的。它是微软公司为构建应用程序用户界面而创建的一种新的描述性语言。XAML提供了一种便于扩展和定位的语法来定义和程序逻辑分离的用户界面,而这种实现方式和ASP.NET中的"代码后置"模型非常类似。XAML是一种解析性的语言,尽管它也可以被编译。它的优点是简化编程式上的用户创建过程,应用时要添加代码等。还有一点是需要反复强调的,XAML并不是HTML。尽管XAML在元素的声明、程序样式的设置和指定事件处理程序上都和HTML非常类似,但是XAML是基于XML的,它是WPF的外在表现形式。而HTML只是一种标记语言,仅仅是用来为浏览器呈现页面内容。XAML除了用来呈现信息和请求用户输入等基本的功能外,它还包含了一些高级的特性,例如它提供了对动画和3D众多方面的支持。XAML是可扩展的,正如它的名字指明的那样。开发人员可以创建自定义的控件、元素和函数来扩展XAML。而且由于XAML各元素在本质上就是WPF类的映射,所以开发人员可以很轻松地使用面向对象的技术对XAML元素进行扩展。也就是说我们可以开发一些自定义控件和组合元素,并将它公开给用户界面设计人员和其它的开发人员使用。
下面先介绍一下XAML的一些基础知识。
先附上一段简单的XAML代码以及详细注释:
1 <Window x:Class="WPFTest.MainWindow" <!-- 类名 --> 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <!-- WPF的默认·命名空间,声明了许多可能用到的控件--> 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" <!-- 声明XAML语言本身--> 4 Title="MainWindow" Height="350" Width="525"> <!-- Title是界面窗口左上角的标题,Height与Width代表整个窗口的高度与宽度--> 5 <Grid> <!-- Grid控件 --> 6 <Button Content="Hello World" <!-- 按钮控件,Content表示按钮上的文本--> 7 HorizontalAlignment="Left" <!-- 设置指定对象的水平对齐方式,此处表示向左对齐--> 8 Margin="200,143,0,0" <!-- 控件距离窗口四边的距离,向左向上的优先级较高--> 9 VerticalAlignment="Top" <!-- 设置指定对象的垂直对齐方式,此处表示向上对齐--> 10 Width="100" <!-- 宽度--> 11 Height="40"/> <!-- 长度--> 12 </Grid> <!-- 结束标记--> 13 </Window>
运行结果如下:
是不是既漂亮又简单?更炫酷的是用VS2013开发WPF的时候可以自由拖拽控件,自动生成相应的XAML代码,从而轻易达到自己想要的排版效果。
下面介绍一下XAML中的布局控件。
先介绍一下主要布局元素的特性:
- Grid:网格。可以自定义行和列,并通过行列的数量、行高和列宽来调整控件的布局,有点类似于html中的Table。
- StackPanel:栈式面板。可以将包含元素排成一条直线,当添加或移除包含元素时,后面的元素会自动向下或向上移动。
- Canvas:画布。可以指定包含元素的绝对坐标位置。
- DockPanel:泊靠式面板。内部元素可以选择泊靠方式。
- WarpPanel:自动折行面板。当一行元素排满后会自动换行。类似html中的流式布局。
Grid的特点如下:
- 可以定义任意数量的行和列
- 行高与列宽可以使用绝对值,相对比以及最大值和最小值
- 内部元素可以设置自己的所在列和行,还可以设置自己跨几列和行。
- 可以设置Children元素的对齐方式
下面是一个比较炫酷的Grid布局的示例,代码及运行效果如下:
1 <Window x:Class="WPFTest.Grid" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="Grid" Height="300" Width="300" MinHeight="300" MaxWidth="500"> 5 <!--MinHeight="300" MaxWidth="500"限制窗口的最小高度和最大宽度--> 6 <Grid x:Name="grid"> 7 <!--定义行--> 8 <Grid.RowDefinitions> 9 <RowDefinition Height="25" ></RowDefinition> 10 <RowDefinition Height="50"/> 11 <RowDefinition Height="1*"/> 12 <RowDefinition Height="*"/> 13 <RowDefinition Height="auto"> 14 </RowDefinition> 15 </Grid.RowDefinitions> 16 <!--定义列--> 17 <Grid.ColumnDefinitions> 18 <ColumnDefinition Width="25" ></ColumnDefinition> 19 <ColumnDefinition Width="50"/> 20 <ColumnDefinition Width="1*"/> 21 <ColumnDefinition Width="*"/> 22 <ColumnDefinition Width="auto"/> 23 </Grid.ColumnDefinitions> 24 <!--在指定的行列中布置控件--> 25 <TextBox Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2" Text="布局" Background="Gray"/> 26 </Grid> 27 </Window>
在后台代码上加上 this.grid.ShowGridLines=true便可显示下列结果:
StackPanel可以把内部的元素在纵向或者横向上紧密排列,形成栈式布局。先介绍一下其三个属性:
- Orientation 决定内部元素是横向还是纵向累积。可取值为Horizontal,Vertical。
- HorizontalAlignment 决定内部元素水平方向上的对齐方式。可取值Left,Center,Right,Stretch。
- VerticalAlignment 决定内部元素竖直方向上的对齐方式。可取Top,Center,Bottom,Stretch。
简单示例如下:
1 <Window x:Class="WPFTest.StackPanels" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="StackPanels" Height="300" Width="300"> 5 <Grid> 6 <StackPanel HorizontalAlignment="Left" Height="128" VerticalAlignment="Top" Width="284" Orientation="Horizontal"> 7 <Button Content="Button" Height="128" VerticalAlignment="Top" Width="75"/> 8 <Button Content="Button" Height="128" VerticalAlignment="Top" Width="75"/> 9 <Button Content="Button" Height="128" VerticalAlignment="Top" Width="75"/> 10 </StackPanel> 11 <StackPanel HorizontalAlignment="Left" Height="128" VerticalAlignment="Top" Width="284" Margin="0,128,0,0" Orientation="Vertical"> 12 <Button Content="Button" HorizontalAlignment="Left" Width="284"/> 13 <Button Content="Button" HorizontalAlignment="Left" Width="284"/> 14 <Button Content="Button" HorizontalAlignment="Left" Width="284"/> 15 </StackPanel> 16 </Grid> 17 </Window>
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Data; 9 using System.Windows.Documents; 10 using System.Windows.Input; 11 using System.Windows.Media; 12 using System.Windows.Media.Imaging; 13 using System.Windows.Navigation; 14 using System.Windows.Shapes; 15 16 namespace WPFTest 17 { 18 /// <summary> 19 /// MainWindow.xaml 的交互逻辑 20 /// </summary> 21 public partial class StackPanel : Window 22 { 23 public StackPanel() 24 { 25 InitializeComponent(); 26 } 27 28 private void InitializeComponent() 29 { 30 throw new NotImplementedException(); 31 } 32 } 33 }
也是非常漂亮!
Canvas(画布):内容控件可以准确定位到指定坐标,但是不足的地方是,如果要修改的话可能会关系到很多的控件,所以如果不需要经常修改的窗体,使用该控件布局,或者是艺术性比较强(用来实现依赖于横纵坐标的动画等功能)的布局使用此控件布局。
下面是一个登陆页面示例来介绍Canvas.Left与Canvas.Top的用法:
1 <Window x:Class="WPFTest.Canvas" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="登陆" Height="145" Width="300"> 5 <Canvas Background="Sienna"> <!-- 设置背景--> 6 <TextBlock Canvas.Left="0" Canvas.Top="13" Margin="5" Text="用户名:"/> 7 <TextBox Canvas.Left="50" Canvas.Top="13" Width="160" /> 8 <TextBlock Canvas.Left="0" Canvas.Top="47" Margin="5" Text="密 码:"/> 9 <TextBox Canvas.Left="50" Canvas.Top="47" Width="160" /> 10 <Button Content="确定" Canvas.Left="70" Canvas.Top="77" Width="63" Height="22" /> 11 <Button Canvas.Left="150" Canvas.Top="77" Content="清除" Width="63" Height="22" /> 12 </Canvas> 13 </Window>
代码简单明了,就不多加注释了,如图所示效果也是十分炫酷!
顾名思义,DockPanel控件允许将控件贴靠在某条边上。DockPanel具有一个能让子控件用来指定停靠边缘的附加属性,即DockPanel.Dock,可将该属性的值设为Left,Right,Top或Bottom。DockPanel中控件的堆叠顺序非常重要,因为每当一个控件停靠在某个边缘上后,其他子控件的可占用空间就会减少。例如,把一个工具条停靠在DockPanel的顶部,再把第二个工具条停靠在DockPanel的左边。第一个控件会延伸到DockPanel显示区域的整个顶部,但第二个控件只能从第一个工具条的底部开始沿着DockPanel的左边界延伸到DockPanel的底部。在前面的子控件都定位好后,最后一个指定的控件通常会占据剩余的空间(可以控制这个行为)。
下面是一个DockPanel布局示例:
1 <Window x:Class="WPFTest.DockPanels" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="DockPanels" Height="300" Width="300"> 5 <DockPanel Background="AliceBlue"> 6 <Border DockPanel.Dock="Top" Padding="10" Margin="5" <!--第一个Border控件停靠在顶部,未指定width,故占满所停靠边缘的整个可用区域--> 7 Background="Aquamarine" Height="45"> 8 <Label>1) DockPanel.Dock="Top"</Label> 9 </Border> 10 <Border DockPanel.Dock="Top" Padding="10" Margin="5" <!--第二个Border控件也停靠在DockPanel的顶部,这个Border控件还包含Width属性,使Border仅占据DockPanel的部分宽度。它位于中心,因为DockPanel中的HorizontalAlignment的默认值是Center--> 11 Background="PaleVioletRed" Height="45" Width="200"> 12 <Label>2) DockPanel.Dock="Top"</Label> 13 </Border> 14 <Border DockPanel.Dock="Left" Padding="10" Margin="5" <!--第三个Border控件停靠在DockPanel的左边,占据显示区域左边的210个像素--> 15 Background="Bisque" Width="200"> 16 <Label>3) DockPanel.Dock="Left"</Label> 17 </Border> 18 19 <Border DockPanel.Dock="Bottom" Padding="10" Margin="5" <!--第四个Border控件停靠在DockPanel的底部,Border控件锁定在DockPanel的右下角,因为它的HorizontalAlignment为Right--> 20 Background="Ivory" Width="200" HorizontalAlignment="Right"> 21 <Label>4) DockPanel.Dock="Bottom"</Label> 22 </Border> 23 <Border Padding="10" Margin="5" Background="BlueViolet"> <!--第五个也是最后一个Border控件填满了剩余的空间--> 24 <Label Foreground="White">5) Last control</Label> 25 </Border> 26 </DockPanel> 27 </Window>
效果是不是特别棒?
WrapPanel控件基本上可以认为是StackPanel的一个扩展版本,其中"不合适"的控件会移动到附加的行或列上。示例代码如下:
1 <Window x:Class="WPFTest.WrapPanel" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WrapPanel" Height="300" Width="300"> 5 <WrapPanel Background="AliceBlue"> 6 <Rectangle Fill="#FF000000" Height="50" Width="50" Stroke="Black" 7 RadiusX="10" RadiusY="10" /> 8 <Rectangle Fill="#FF111111" Height="50" Width="50" Stroke="Black" 9 RadiusX="10" RadiusY="10" /> 10 <Rectangle Fill="#FF222222" Height="50" Width="50" Stroke="Black" 11 RadiusX="10" RadiusY="10" /> 12 <Rectangle Fill="#FFFFFFFF" Height="50" Width="50" Stroke="Black" 13 RadiusX="10" RadiusY="10" /> 14 </WrapPanel> 15 </Window>
缩小之后如下所示:
非常好玩。总之WrapPanel控件是创建动态布局的一种好方法,允许我们控制内容的显示方式。
本次学习记录就先到此为止,以后有机会会补上UI控件的有关内容以及更加高级一些的WPF桌面编程。
望各位老师大牛不吝赐教!