XAML
XAML (Extensible Application Markup Language) 是一种基于 XML 的标记语言。在 WinUI 中,它可以像写说明书一样定义界面。如果你写过 HTML,你会对这种由标签组成的语言很眼熟。让我们打开 MainWindow.xaml ,这里定义了程序运行时的主界面。
在此之前,请自行编译或在微软商店中下载 WinUI 3 Gallery,此应用展示了所有可用的 WinUI 3 控件和样式。
XAML 是什么
在传统的 C# 编程中,你创建一个界面需要写很多“命令式”的代码:
| |
而 XAML 将上述过程序列化为一种文本格式:
| |
当程序运行时,XAML 解析器会读取这段 XML,根据标签名去内存里 new 出对应的对象,根据属性名去调用 set 操作,最后根据层级关系把它们组装成一棵对象树(Object Tree)。
在设计上,XAML 是“部分类(Partial Class)”的 UI 延伸。
在 WinUI 中,你经常会看到一个 XAML 文件对应一个 .xaml.cs 文件。
XAML 文件: 定义了类的外在结构(UI 元素、布局)。
Code-behind (.cs): 定义了类的内在逻辑(事件处理、业务计算)。
通过 XAML 顶部的 x:Class="MyApp.MainWindow",编译器会将这两部分合并。
本质上 XAML 被编译成了 C# 或 C++ 代码。你在 XAML 里写的
<Button x:Name="myButton" />,编译器会自动在后台生成一个private Button myButton;的成员变量。这就是为什么你可以在
.cs文件里直接操作 XAML 里定义的控件。
XAML 的强大不仅仅在于创建对象,而是在于它引入了依赖属性(Dependency Properties)和标记扩展(Markup Extensions)。
依赖属性: 传统的 OOP 对象属性只是简单的变量。而 XAML 对象的属性是可以“监听”的。当一个数据源变了,XAML 里的 UI 会自动变化。
标记扩展(花括号语法): 例如
{Binding ...}或{ThemeResource ...}。这证明了 XAML 不仅仅是静态文本。
花括号里的内容是一段会在运行时执行的小脚本。它告诉 XAML 解析器:“不要直接给这个属性赋值字符串,而是去执行一段逻辑(比如去寻找绑定的数据源,或者去系统设置里查一下现在的颜色主题)”。
XAML 是“视觉树(Visual Tree)”的构建工具。在 WinUI 中,界面是由成百上千个微小的对象组成的,如果你用代码去维护这些对象的层级关系(父子关系、嵌套关系),代码会变得极其混乱且难以维护。
XAML 解决了“复杂层级的可视化表达”:
它用 XML 的嵌套结构完美映射了 UI 的树状结构。
它让开发者能够以上帝视角俯瞰整个界面的布局,而不需要关心对象是如何在一个个内存地址中被链接起来的。
简单来讲,XAML 是为了让开发者能够用“描述结果”的方式,去编写原本需要通过大量“命令代码”才能构建出来的复杂 OOP 对象树。
一些基础语法
一、基础属性声明方式
1. 属性语法(Attribute Syntax)
直接在元素标签中以 属性="值" 形式声明:
| |
适用于字符串、数字、布尔值、枚举、简单结构体(如
Thickness)等无法设置复杂对象(如
Style、DataTemplate)
2. 属性元素语法(Property Element Syntax)
当属性值是复杂对象时,使用子元素形式:
| |
适用于:
Brush、Style、DataTemplate、ControlTemplate等两种语法等价转换:
1 2 3 4 5 6 7 8 9<!-- 属性语法 --> <Button Background="Red"/> <!-- 属性元素语法 --> <Button> <Button.Background> <SolidColorBrush Color="Red"/> </Button.Background> </Button>
二、特殊属性类型
1. 附加属性(Attached Properties)
由其他类型定义、附加到当前元素的属性,语法:定义类型.属性名:
| |
常见附加属性:
Grid.Row/Grid.ColumnCanvas.Left/Canvas.TopScrollViewer.VerticalScrollBarVisibility
2. 依赖属性(Dependency Properties)
WinUI 控件属性底层基于依赖属性系统,支持:
数据绑定
动画
样式设置
属性值继承
开发者通常无需直接操作依赖属性,但理解其存在有助于调试绑定/样式问题。
三、属性值类型与转换器
XAML 通过 类型转换器(TypeConverter) 将字符串自动转换为目标类型:
| 属性类型 | 示例 | 说明 |
| 字符串 | Content="Hello" | 直接赋值 |
| 数字 | Width="200" | 转为 double |
| 布尔值 | IsEnabled="False" | True/False(不区分大小写) |
| 枚举 | HorizontalAlignment="Center" | 枚举成员名 |
| 颜色 | Background="Red" | 预定义颜色名 / #FF0000 / #FFFF0000 |
| Thickness | Margin="10,5,10,5" | 顺序:左,上,右,下(支持 1/2/4 个值) |
| DateTime | DatePicker.Date="2024-01-15" | ISO 8601 格式 |
💡 自定义类型需实现
TypeConverter或使用属性元素语法。
四、标记扩展(Markup Extensions)
标记扩展以 {} 包裹,用于动态解析属性值:
1. 资源引用
| |
2. 数据绑定
| |
| 特性 | x:Bind | Binding |
| 性能 | ⚡ 编译时生成代码 | 🔁 运行时反射 |
| 类型安全 | ✅ 有 | ❌ 无 |
| 默认 Mode | OneTime | OneWay |
| 路径起点 | 页面/用户控件 | DataContext |
3. 其他常用标记扩展
| |
五、事件声明语法
事件通过属性语法直接关联后台方法:
| |
| |
事件处理器必须是
partial class中的private方法参数类型需匹配路由事件签名(通常为
(object, RoutedEventArgs))
六、命名空间与 x: 前缀
1. 核心命名空间
| |
xmlns:默认 WinUI 控件命名空间xmlns:x:XAML 语言基础特性(如x:Name,x:Key)xmlns:local:自定义类型命名空间
2. 关键 x: 指令
| 指令 | 用途 | 示例 |
x:Name | 代码中引用元素 | <Button x:Name="myButton"/> → myButton.Content = "New"; |
x:Key | 资源字典中标识资源 | <Style x:Key="MyStyle" TargetType="Button"/> |
x:Class | 指定后台代码类 | <Page x:Class="MyApp.MainPage"> |
x:Load | 条件性加载元素(WinUI 3.0+) | <Button x:Load="{x:Bind IsAdmin}"/> |
x:Phase | 优化列表虚拟化加载 | <TextBlock x:Phase="1"/> |
七、属性路径(Property Path)
用于绑定/动画中访问嵌套属性:
| |
布局
不同于 HTML 从上到下的流式布局,XAML 使用“容器”的概念来管理布局。因为 Windows 窗口可以拉大拉小,屏幕分辨率也各不相同,XAML 采用的是一种比例化的布局方案,而不是将坐标固定死。你可以把布局想象成是在不同的盒子里装东西。
Grid(网格)
Grid 是 WinUI 中最灵活、最强大的布局控件之一。它允许你通过行(Rows)和列(Columns)来划分空间,类似 Excel 表格。
在使用 Grid 时,需要先定义行与列。
| |
Grid 的三种尺寸单位:
绝对尺寸 (如
100):固定的像素值,不随窗口大小而变化。自动尺寸 (
Auto):控件有多大,格子就缩放成多大。比例尺寸 (
*):自适应布局的关键。如果第一列是1*,第二列是2*,则第二列永远是第一列宽度的两倍。
*是1*的简写,在定义了绝对尺寸和自动尺寸之后,*会自动分配剩余的空间 。
| |
试着调整窗口高度,看看布局是否正确发生了变化。
StackPanel(堆栈面板)
StackPanel 是一种简单直观的布局容器,用于将子元素沿单一方向(水平或垂直)线性排列。适合构建列表式、流式布局。
| |
| |
运行Sample 3 ,你会看到三个按钮都靠在左上角。我们可以通过HorizontalAlignment 与 VerticalAlignment 属性来更改对齐行为。
控件
控件是界面上真正能被用户感知与交互的元素。
文本控件
TextBlock —— 静态文本
| |
如果你希望文本可以被选中,使用IsTextSelectionEnabled="True"
TextBox —— 输入框
| |
如果需要输入密码,则应该使用PasswordBox控件
按钮
Button —— 标准按钮
| |
在.xaml.cs代码中处理事件绑定,并通过IsEnabled属性控制其可用性
DropDownButton —— 带下拉菜单的按钮
| |
ToggleSwitch —— 开关控件
| |
集合控件(Collection Controls)
具体的控件演示可以在 WinUI 3 Gallery 的Collections中找到。在这里先介绍DataTemplate 与 ItemTemplate的概念。
DataTemplate
DataTemplate定义了展示数据项的模板。假设我们有一个Person类:
| |
如果我们想在界面上展示一个或多个Person对象,就需要先定义它长什么样。
| |
上述代码定义了一个用于Person类型的DataTemplate,其中用StackPanel垂直排布了两个TextBlock,分别用于展示Name和Age。DataTemplate不是控件,而是模板定义,通过 {x:Bind} 将数据属性映射到 UI 元素。
ItemTemplate
ItemTemplate是ItemsControl及其派生类(ListView/GridView/ComboBox)的属性,指定集合中的每一项使用哪个 DataTemplate 渲染。是控件的属性(不是独立元素),其值类型为 DataTemplate。
| |
完整的ListView示例:
| |
后台代码示例:
| |