第一步是执行所需的更改的基本设置:
- 启用导航缓存。
- 为
Note.Text属性实现属性更改通知。
完成此操作后,你将调整应用的其他部分以处理这些更改。
Tip
可以从 WinUI Notes 第 2 部分的 GitHub 存储库下载或查看本教程的完整代码。 若要查看项目的起点和终点之间的差异,请参阅此提交: 第 2 部分的更新。
启用 NavigationCacheMode
默认情况下,每次导航时,都会使用其默认值创建新的 Page 实例。 在 WinUI Notes 应用中,这也是创建 notesModel 的地方,它用于存储所有 Note 实例。
在 AllNotesPage.xaml中,将 NavigationCacheMode 设置为 Enabled (NavigationCacheMode="Enabled")。 启用 NavigationCacheMode 后,将保留相同的页面实例,因此每次导航时都不会创建新的 Page 实例,并且不会重新创建 notesModel。
<Page
x:Class="WinUI_Notes.Views.AllNotesPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI_Notes.Views"
xmlns:models="using:WinUI_Notes.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
// ↓ Add this. ↓
NavigationCacheMode="Enabled">
立即运行应用,你将注意到此更改的一些副作用。
- 编辑现有笔记时,返回后,所做的更改不会显示在“所有笔记”页面中。
- 创建并保存新笔记时,导航回时不会显示在所有备注列表中。
- 删除已有的笔记后,返回时,该笔记不会从所有笔记列表中移除。
你接下来将修复这些问题。
在文档中了解详细信息:
实现 INotifyPropertyChanged
编辑并保存现有笔记时,更改将保存到文件系统,但更改不会传播到所有备注列表。 这是因为 Note 类不会通知将 TextBox 连接到 Note 文本的数据绑定已发生更新。 若要使此通知发生,Note类需要为其INotifyPropertyChanged属性实现Text接口。
Note
WinUI 包含 Microsoft.UI.Xaml.Data.INotifyPropertyChanged 接口。 这仅由不使用.NET的 C++ 应用使用。
使用 .NET创建的 C# 应用改用 System.ComponentModel.INotifyPropertyChanged 接口。
INotifyPropertyChanged 的实现遵循一种固定模式。
为所需的命名空间添加
using语句。// ↓ Add this. ↓ using System.ComponentModel using System.Runtime.CompilerServices实现
INotifyPropertyChanged。 该Note类现在实现此接口。// ↓ Update this. ↓ public class Note : INotifyPropertyChanged为
_text属性创建后盾字段 (Text)。// ↓ Delete this. ↓ // public string Text { get; set; } = string.Empty; // ↓ Add this. ↓ private string _text = string.Empty;将
Text属性修改为使用带有属性更改通知的 getter/setter 模式。// ↓ Add this. ↓ public string Text { get => _text; set { if (_text != value) { _text = value; OnPropertyChanged(); } } }添加
INotifyPropertyChanged接口所需的 PropertyChanged 事件。// ↓ Add this. ↓ public event PropertyChangedEventHandler? PropertyChanged;添加
OnPropertyChanged方法。 此帮助程序方法使用PropertyChanged属性引发事件,用于自动属性名称检测。// ↓ Add this. ↓ protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
Tip
可以使用GitHub Copilot在应用中快速实现INotifyPropertyChanged。 这些代码更改是使用提示生成的:“为 Note.Text 属性实现 INotifyPropertyChanged”。
绑定模式
现在,每当其值更改时,该 Text 属性都会通知绑定到它的任何 UI 元素,以便可以自动更新 UI。 但是,为了使绑定的 UI 元素对更新通知做出响应,必须确保使用了正确的 BindingMode 。
Important
选择正确的 BindingMode 非常重要;否则,数据绑定可能无法按预期工作。 (使用 {x:Bind} 时的一个常见错误是,在需要 OneWay 或 TwoWay 时忘记更改默认 BindingMode。)
| Name | Description |
|---|---|
OneTime |
仅在创建绑定时更新目标属性。 默认值为 {x:Bind}. |
OneWay |
在创建绑定时更新目标属性。 对源对象的更改也可以传播到目标。 |
TwoWay |
在任一更改时更新目标对象或源对象。 创建绑定后,将从源更新目标属性。 |
在 AllNotesPage.xaml 中,找到 Page.Resources 中的 NoteItemTemplate。 然后,在模板中找到与 Text 属性绑定的 TextBlock。 更新绑定以使用 OneWay 绑定模式。
// ↓ Update this. ↓ ↓ ↓
<TextBlock Text="{x:Bind Text, Mode=OneWay}"
Margin="4" TextWrapping="Wrap"
TextTrimming="WordEllipsis"/>
由于用户无法更新 TextBlock 中的文本,因此只需要一个 OneWay 绑定,从源(Note.Text)到目标(TextBlock.Text)。
在文档中了解详细信息: