XAML使用标签来定义Ul元素(UIElement),每个标签对应NET Framework类库中的一个控件类。通过设置标签的Atribute,不但可以对标签所对应控件对象的Property进行赋值,还可以做一些额外的事件(如声明命名空间、指定类名等)。

树形结构

在界面上添加一些控件,界面如下:

界面的XAML如下所示:

<Window x:Class="LearnWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LearnWpf"
mc:Ignorable="d"
Title="MainWindow" Height="164.458" Width="344.578">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="69*"/>
<ColumnDefinition Width="19*"/>
</Grid.ColumnDefinitions>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,33,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="245"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="10,91,0,0" VerticalAlignment="Top" Width="245" Height="21"/>
<StackPanel HorizontalAlignment="Left" Height="25" Margin="10,61,0,0" VerticalAlignment="Top" Width="245" Orientation="Horizontal">
<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
</StackPanel>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="245" />
</Grid>
</Window>

可以看出UI是平面结构,XAML是树形结构,而且同一种UI布局界面的XAML代码可以有多种实现。在开发时,可以通过WPF基本类库中的VisuaTreeHelper和LogicarTreeHelper两个助手类操作XAML树。

VS2019可以通过“视图->其他窗口->文档大纲”查看XAML代码的结构,如图所示:

对象属性赋值语法

XAML是一种声明性语言,在文档只能使用标签声明对象、初始化对象的属性。XAML中为对象属性赋值共有两种语法:

  • 使用字符串(标签的Attribute)进行简单赋值
  • 使用属性元素(Property Element)进行复杂赋值。

注:能使用Attribute=Value形式赋值的就不使用属性元素

使用标签的Attribute

一个标签的Attribute里有一部分与对象的Property互相对应,如<Rectangle>标签的Fill这个Attribute与Rectangle类对象的Fill属性对应。Rectangle.Fill的类型Brush是一个抽象类,凡是以Brush为基类的类都可作为Fill属性的值。

使用字符串对Atribute进行简单赋值,让Rectangle填充成单一的蓝色,XAML代码(省略了Window标签)如下:

<Grid>
<Rectangle x:Name="rectangle" Fill="Blue" HorizontalAlignment="Left" Height="100" Margin="70,17,0,0" Stroke="Black" VerticalAlignment="Top" Width="100"/>
</Grid>

上面的“Blue”最终被翻译成了SolidColorBrush对象,等效C#代码如下:

SolidColorBrush sBrush = new SolidColorBrush();
sBrush.Color = Colors.Blue;
this.rectangle.Fill = sBrush;

使用属性元素

属性元素指的是某个非空标签的一个元素(夹在起始标签和结束标签之间的一些子级标签)对应这个标签的一个属性,即以元素的形式来表达一个实例的属性。

上面Attribute赋值的例子可以用属性元素的方式实现,XAML(省略了Window标签)代码如下:

<Grid>
<Rectangle x:Name="rectangle" HorizontalAlignment="Left" Height="100" Margin="70,17,0,0" Stroke="Black" VerticalAlignment="Top" Width="100">
<Rectangle.Fill>
<SolidColorBrush Color="Blue"/>
</Rectangle.Fill>
</Rectangle>
</Grid>

属性元素语法的优势在属性是复杂对象时才能体现出来,比如线性渐变画刷填充矩阵代码(省略了Window标签):

<Grid>
<Rectangle x:Name="rectangle" HorizontalAlignment="Left" Height="100" Margin="70,17,0,0" Stroke="Black" VerticalAlignment="Top" Width="100">
<Rectangle.Fill>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.2" Color="LightBlue"/>
<GradientStop Offset="0.7" Color="Blue"/>
<GradientStop Offset="1.0" Color="DarkBlue"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>

扩展:标记扩展(Markup Extensions)

上面大多数赋值都是为属性生成一个新对象,当需要为对象的属性进行特殊类型赋值时就需要使用标记扩展了,如:

  • 把同一个对象赋值给两个对象的属性
  • 给对象的属性赋一个null值
  • 将一个对象的属性值依赖在其他对象的某个属性上

标记扩展是一种特殊的Atribule=Value语法,Value字符串是由一对花括号及其括起来的内容组成,XAML编译器会对这样的内家做出解析并生成相应的对象。

使用Binding类的实例将TextBox的Text属性依赖在Slider的Value上,当Slider的滑块滑动时TextBox就会显示Slider当前的值,XAML代码(省略了Window标签)如下:

<Grid>
<StackPanel HorizontalAlignment="Left" Height="115" Margin="10,10,0,0" VerticalAlignment="Top" Width="205">
<TextBox Height="23" TextWrapping="Wrap" Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}"/>
<Slider x:Name="slider1" Margin="0,5,0,0"/>
</StackPanel>
</Grid>

Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}"就是标记扩展,对象的数据类型名是紧邻左花括号的字符串,对象的属性由一串以逗号连接的子字符串负责初始化(不加引号)

标记扩展也是对属性的赋值,完全可以使用属性标签的形式来替换标记扩展,但基本上没人这么做(太不简洁了)。

只有MarkupExtension类的派生类(直接或间接均可)才能使用标记扩展语法来创建对象,后面会主要说明下面几种:

  • MarkupExtension的直接派生类并不多,它们是:
  • System.Windows.ColorConvertedBitmapExtension
  • System.Windows.DynamicResourceExtension
  • System.Windows.ResourceKey
  • System.Windows.StaticResourceExtension
  • System.Windows.TemplateBindingExtension
  • System.Windows.ThemeDictionaryExtension
  • System.Windows.Data.BindingBase
  • System.Windows.Data.RelativeSource
  • System.Windows.Markup.ArrayExtension
  • System.Windows.Markup.NullExtension
  • System.Windows.Markup.StaticExtension
  • System.Windows.Markup.TypeExtension

扩展:使用TypeConverter 类映射Atribute与Property

有时候我们有一些自定义的类需要使用XAML语言进行声明,并允许它的Property与XAML标签的Atribute互相映射,那就需要为这些Property准备适当的转换机制

下面以自定义类Human为例演示TypeConverter的用法,XAML代码(省略了Window标签)如下:

<Window.Resources>
<local:Human x:Key="human" Child="AB" />
</Window.Resources>
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="61,40,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
//按钮事件
private void Button_Click(object sender, RoutedEventArgs e)
{
Human h = (Human)this.FindResource("human");
MessageBox.Show(h.Child.Name);
} /// <summary>
/// 以绑定转换器的目标类型Human(TypeConverter是TypeConverterAttribute的简写)
/// </summary>
[TypeConverter(typeof(StringToHumanlypeConverter))]
public class Human
{
public string Name { get; set; }
public Human Child { get; set; }
} /// <summary>
/// 字符串转目标类型Human的转换器
/// </summary>
public class StringToHumanlypeConverter : TypeConverter
{
//运行时转换源类型为此目标类型,缺少此方法的重载会使运行时类型转换异常
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
{
Human h = new Human();
h.Name = value as string;
return h;
}
return base.ConvertFrom(context, culture, value);
}
//设计时判断是否支持源类型到目标类型的转换,缺少此方法的重载会使UI设计器异常
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
}

需要注意的是TypeConverter的ConvertFrom、CanConvertFrom两个方法必须同时重载,只有前者会导致设计时界面异常、运行时数据转换正常,只有后者会导致设计时界面正常、运行时数据转换异常。

事件处理器

一个XAML标签对应着一个对象时,这个标签的一部分Atribute会对应这个对象的Property,还有一部分Attribute对应着对象的事件(Event)

标签有一个名为Click的Attribute,它对应的就是Buton类的Click事件,如下所示:

<Grid>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="61,40,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
</Grid>

注:右键Click="Button_Click"->“转到定义”,会自动生成一个空的事件处理函数

等效的C#代码如下所示:

Button buttonl = new Button();
buttonl.Click += new RoutedEventHandler(buton1_Click);

由于C#的partial类和XAML标签的x.Class特征,开发软件时完全可以把用于实现程序逻辑的C#代码放在一个文件里,把用于描述程序U1的XAML代码放在另一个文件里,并且让事件性Attribute充当XAML与C#之间沟通的纽带。这种将逻辑代码与UI代码分离、隐藏在UI代码后面的形式就叫作“代码后置”(Code-Behind)。当然,事件代码也可以使用标签x:Code直接写到XAML里面

导入程序集及引用命名空间

在XAML中引用命名空间的语法是:

xmlns:映射名="clr-namespace:类库中命名空间的名字;assembly=类库文件名"
  • xmlns是用于在XAML中声明命名空间的Attribute,从XML语言继承而来(XML Namespace的缩写)。
  • 冒号后的映射名是可选的,但由于可以不加映射名的默认命名空间已经被WPF的主要命名空间占用,所以所引用的命名空间都需要加上这个映射名。映射名可以自由选择,建议使用类库中命名空间的原名或者缩写
  • 引号中的字符串值确定了要引用的是哪个类库以及类库中的哪个命名空间。

使用引用命名空间中的类的语法如下:

<映射名:类名>.…</映射名:类名>

C#中也可以给命名空间设置映射名,但没什么意义,如:

using Cmn=Common;
using Cu=Controls;

XAML的注释

XAML的注释语法亦继承自XML,语法是:

<!--需要被注释掉的内容-->
  • XAML注释只能出现在标器的内容区域,即只能出现在开始标签和结来标签之阔。
  • XAML注释不能用于注释标签的Attribute。
  • XAML注释不能嵌套。

WPF之XAML语法的更多相关文章

  1. WPF 基础 - xaml 语法总结

    Attribute 与 Property 之间的区别 Property 对应着抽象对象身上的性状: Attribute 是针对标签的特征: 往往一个标签具有的 Attribute 对于它所代表的对象的 ...

  2. 4 WPF学习---系统的学习XAML语法

    转载:http://blog.csdn.net/fwj380891124/article/details/8093001 1,XAML文档的树形结构: UI在用户眼里面是个平面结构.如下图所示,在用户 ...

  3. XAML属性赋值转换之谜(WPF XAML语法解密)

    XAML与XML类似,就是XML延伸过来的.为了更好的表达一些功能,WPF对XML做了扩展,有些功能是WPF在后台悄悄的替你做了.有时候,虽然实现了某个功能,但是对实现原理还是很茫然.今天就讲讲XAM ...

  4. WPF中 PropertyPath XAML 语法

    原文:WPF中 PropertyPath XAML 语法 PropertyPath 对象支持复杂的内联XAML语法用来设置各种各样的属性,这些属性把PropertyPath类型作为它们的值.这篇文章讨 ...

  5. WPF:XAML概述

    简介 XAML是eXtensible Application Markup Language可扩展应用程序标记语言,它是微软公司为构建应用程序用户界面而创建的一种新的描述性语言.XAML提供了一种便于 ...

  6. wpf中xaml的类型转换器与标记扩展

    原文:wpf中xaml的类型转换器与标记扩展 这篇来讲wpf控件属性的类型转换器 类型转换器 类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是可以由xaml组成的,所以标签的便利也需 ...

  7. .Net Core WPF之XAML概述

    原文链接,机器翻译,有误处参看原文. XAML overview in WPF 2019/08/08 What is XAML XAML syntax in brief Case and white ...

  8. Xaml语法概述及属性介绍

    Xaml语法概述 1.命名空间     xmal每个元素都对应着一个类,但是在xmal中,只提供类名是不够的,需要知道该类实在.net的哪个命名空间下面.Xaml解析器才能够正确的解析. 1 < ...

  9. 基本 XAML 语法指南

    我们介绍了 XAML 语法规则,以及用于描述 XAML 语法中存在的限制或选项的术语.当出现以下情况时你会发现本主题很有用:不熟悉 XAML 语言的使用,希望加强对术语或某些语法部分的理解,或者对 X ...

  10. How can I list colors in WPF with XAML?

    How can I get list of all colors I can pick in Visual Studio Designer (which is System.Windows.Media ...

随机推荐

  1. 3.2 DLL注入:远程APC异步注入

    APC(Asynchronous Procedure Call)异步过程调用是一种Windows操作系统的核心机制,它允许在进程上下文中执行用户定义的函数,而无需创建线程或等待OS执行完成.该机制适用 ...

  2. vscode连不上云服务器,一直报超时错误|但是xshell那些又可以连上?为什么vscode连不上?|命令行输出管道报错 -bash: command not found 导致的一系列问题

    前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总https://blog.cs ...

  3. 利用ogg实现oracle到kafka的增量数据实时同步

    前言 ogg即Oracle GoldenGate是Oracle的同步工具,本文讲如何配置ogg以实现Oracle数据库增量数据实时同步到kafka中,其中同步消息格式为json. 下面是我的源端和目标 ...

  4. [Ngbatis源码学习][SpringBoot] ApplicationContextInitializer接口类的使用和原理解读

    ApplicationContextInitializer接口类的使用和原理解读 在看Ngbatis源码的过程中,看到了自定义的ApplicationContextInitializer实现类,对Ap ...

  5. JS 记一次工作中,由深度优先到广度优先的算法优化

    壹 ❀ 引 坦白的说,本人的算法简直一塌糊涂,虽然有刷过一段时间的算法题,但依然只能解决不算复杂的问题,稍微麻烦的问题都只是站在能不能解决问题的角度,至于性能优化,算法方法的选择并没有过于深刻的理解. ...

  6. 从零开始的微信小程序入门教程(二),初识WXML与WXSS

    壹 ❀ 引 时隔大半年,我终于开始写小程序入门教程的第二篇了,其实我也在纳闷,这么久的时间我到底干了什么,仔细一想,我学了JavaScript部分进阶知识,学了ES6,系统性的去复习了angularj ...

  7. 开源神器:自动生成随机 mock 数据测试对象

    测试的痛点 大家好,我是老马. 每一位开发者大部分工作都是写代码.测试代码.修BUG. 我们有很多测试代码,总是花费大量的实践去构建一个对象. 于是就在想,能不能自动填充一个对象呢? 于是去 gith ...

  8. 从零开始手写 redis(三)内存数据重启后如何不丢失?

    前言 我们在 从零手写 cache 框架(一)实现固定大小的缓存 中已经初步实现了我们的 cache. 我们在 从零手写 cache 框架(一)实现过期特性 中实现了 key 的过期特性. 本节,让我 ...

  9. win32 - 虚拟内存的一些介绍

    对32位Windows来说,其虚拟地址空间总数就是2的32次方,即4GB. 如果没有在引导时加上/3GB或/BOOTVA选项,Windows默认最大会分2GB给内核模式程序使用,2GB给用户模式程序. ...

  10. SpringBoot 服务接口限流,搞定!

    来源:blog.csdn.net/qq_34217386/article/details/122100904   在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.限流可以认为服务降级的一种 ...