WinUI 3 数据绑定:如何让 UI 自动更新?
1. 什么是 UI 自动更新
想象一个最常见的场景:
你在一个输入框里打字,屏幕另一边的文字标签同步变化,不需要你点任何“保存”或“刷新”按钮。
这就是 UI 自动更新。
没有数据绑定的做法

数据变化的地方越多,这种“手动搬运”的代码就越多。改一个字段漏掉一个地方,界面就会显示不一致。
有数据绑定的做法

中间两步完全由框架完成。你只需要做一件事:告诉 UI 和数据之间是什么关系。
下图展示了一个可输入文本框和一个展示文字的文本标签,当在文本框输入文字时,文字自动传递给绑定变量,然后又反向绑定到文本标签,实现了实时自动更新。
2. 让 UI 自动更新的两个核心
2.1 数据绑定:建立连接
在 XAML 中声明“这个控件的这个属性,等于那个数据的那个属性”。
比如:
<TextBlock Text="{x:Bind 用户姓名}" />
这行代码的意思:这个 TextBlock 显示的内容,永远等于“用户姓名”这个数据。
不需要写任何 C# 代码来赋值。
2.2 INotifyPropertyChanged:发送通知
这是初学者最容易踩的坑。
普通 C# 属性变化时,WinUI 不会自动感知。你必须让数据类主动说一声“我变了”。
// 这样写,UI 不会更新 ❌ public string 用户姓名 { get; set; } // 这样写,UI 会自动更新 ✅ private string _用户姓名; public string 用户姓名 { get => _用户姓名; set { _用户姓名 = value; 通知UI我变了(); // 关键 } }
通知的方式有多种:
方式一:原生 INotifyPropertyChanged
继承 INotifyPropertyChanged,实现 OnPropertyChanged 接口,并在绑定变量变化时调用通知接口。
public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
方式二:借助 CommunityToolkit.Mvvm
使用现成的 .NET 库来简化通知过程。
3. 基本示例:制作一个简单的应用启动器
用一个实际项目来串起所有概念。界面很简单:
-
GridView 网格展示应用列表(图标 + 名称)
-
点击某个应用后,启动该应用

3.1 项目结构
这里简化结构,主要包含两大部分:
-
ViewModel(视图模型):包含了数据定义,并负责通知
-
MyAppsPage(界面):XAML,负责显示
3.2 数据模型
定义每个 App 应用长什么样,主要信息包含:图标、名称、描述。
3.3 视图模型
这是整个数据绑定的中枢。
这里主要暴露一个应用列表,用 ObservableCollection 类型,这样增删应用时 UI 会自动刷新。
public class AppLauncherViewModel : ObservableObject { public static ObservableCollection<AppInfo> AppItems; }
3.4 界面 XAML
核心绑定写法:
| XAML 中的写法 | 含义 |
|---|---|
ItemsSource="{x:Bind AppItems}" |
GridView 的数据来源是 ViewModel 里的 Apps 列表 |
Text="{x:Bind Icon}" |
DataTemplate 内部绑定到当前项的 Icon 图标 |
Text="{x:Bind Name}" |
DataTemplate 内部绑定到当前项的 Name |
3.5 运行效果
最终运行起来如下所示:
-
界面展示一行应用图标和名称
-
鼠标点击任意应用,启动对应 App
全程没有写任何“点击 → 找控件 → 赋值”的代码。
4. 小结
如果发现绑定未生效,最可能的原因主要如下:
| 现象 | 可能的原因 |
|---|---|
| 数据变了,UI 不动 | 属性没实现 INotifyPropertyChanged |
| 列表新增了数据,GridView 不显示 | 用了 List 而不是 ObservableCollection |
WinUI 3 的数据绑定,主要就是两件事:
-
声明关系:XAML 里用绑定语法
-
发出通知:ViewModel 实现 INotifyPropertyChanged
理解这套关系后,写 UI 就变成“描述数据长什么样”,而不是“搬运数据”。代码量减少,bug 也减少。



