将注释作为导航参数传递

现在 Note 已拥有 State,请更新导航逻辑,将其传递回 AllNotesPage,在那里您可以根据其 State 进行相应处理。 这也使你有机会改善与导航相关的用户体验。

Tip

如果需要,请查看 创建第一个 WinUI 3 应用,步骤 1 - 导航。 在进行这些更改之前,了解导航的设置方式很有帮助。

目前,从 NotePage 后到回 AllNotesPage 的所有导航都是通过对 Frame.GoBack 的简单调用完成的。 但是,该方法 GoBack 不允许传递导航参数。 为了将 Note 作为参数传递,你需要将后退导航替换为前向导航(Frame.Navigate)。 此外,GoBack 不会像向前导航那样向导航堆栈添加条目,因此您需要管理后退堆栈,以防止此向前导航被添加。

Tip

可以从 WinUI Notes 第 2 部分的 GitHub 存储库下载或查看本教程的完整代码。 若要查看项目的起点和终点之间的差异,请参阅此提交: 第 2 部分的更新

OnNavigatingFrom

NotePage.cs 中,重写 的 OnNavigatingFrom 方法。 在用户按下后退按钮并调用 GoBack 后调用此功能。 它允许你拦截导航、检查注释 State,并在需要时取消导航。

此处,如果未保存笔记,则取消后退导航并显示一个对话框,询问用户是否要保存笔记。

  • 如果用户保存该笔记,则调用 SaveAsync,然后将返回导航替换为对 Navigate 的调用,并将该笔记传递给 AllNotesPage
  • 如果用户未保存更改,请使用 TextBox.Undo 撤消任何编辑,重置笔记状态,然后重启后退导航。
// ↓ Add this. ↓
protected async override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    if (noteModel?.State == NoteState.Unsaved)
    {
        e.Cancel = true;
        ContentDialog dialog = new ContentDialog();

        // XamlRoot must be set for the ContentDialog.
        dialog.XamlRoot = this.XamlRoot;
        dialog.Title = "Save your work?";
        dialog.PrimaryButtonText = "Save";
        dialog.SecondaryButtonText = "Don't Save";
        dialog.CloseButtonText = "Cancel";
        dialog.DefaultButton = ContentDialogButton.Primary;

        ContentDialogResult result = await dialog.ShowAsync();

        if (result == ContentDialogResult.Primary)
        {
            await noteModel.SaveAsync();
            Frame.Navigate(typeof(AllNotesPage), noteModel);
        }
        else if (result == ContentDialogResult.Secondary)
        {
            while (NoteEditor.CanUndo)
            {
                NoteEditor.Undo();
            }
            NoteEditor.Focus(FocusState.Programmatic);
            noteModel.State = NoteState.Saved;
            Frame.Navigate(typeof(AllNotesPage), noteModel);
        }
    }
}

Delete

接下来,修改 NotePage.xaml.cs 中删除按钮 Click 事件的代码。 你不会只是删除该笔记并返回,而是会检查该笔记的状态。

  • 如果状态为 Unset - 这意味着笔记是新创建的,没有任何编辑,并且尚未保存 - 只需导航回去。 你无需将该说明作为参数传递。
  • 否则,请从文件系统中删除笔记文件,并将 Note 对象作为导航参数传回。 然后 AllNotesPage 将接收带有其 Deleted 状态的 Note,并知道将其从 Notes 集合中删除。
private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{
    if (noteModel is not null)
    {
        if (noteModel.State == NoteState.Unset)
        {
            // If the note is new, doesn't have any edits,
            // and hasn't been saved, just call GoBack.
            // There's no need to pass back the noteModel.
            if (Frame.CanGoBack == true)
            {
                Frame.GoBack();
            }
        }
        else
        {
            // If the note has been saved before, then delete it
            // and navigate back to the AllNotesPage passing the
            // noteModel with its Deleted state.
            await noteModel.DeleteAsync();
            Frame.Navigate(typeof(AllNotesPage), noteModel);
        }
    }
}

保存并关闭

目前,用户必须单击以保存笔记,然后单击后退箭头关闭笔记页,然后返回到笔记集合。 通过允许用户保存和关闭笔记,只需单击一下即可改进此体验。 为此,你将将“保存”按钮替换为“保存并关闭” SplitButton ,并使用下拉列表选项来仅保存。

<!-- ↓ Delete this. ↓ -->
<!--<Button Content="Save" Click="SaveButton_Click"/>-->

<!-- ↓ Add this. ↓ -->
<SplitButton Content="Save &amp; close" Click="SaveCloseButton_Click"
             Height="32">
    <SplitButton.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem Text="Save" Click="SaveButton_Click"/>
        </MenuFlyout>
    </SplitButton.Flyout>
</SplitButton>

为“保存并关闭”按钮 Click 事件添加新事件处理程序。 在这里,先保存笔记,然后将其作为导航参数传回给 AllNotesPage

// ↓ Add this. ↓
private async void SaveCloseButton_Click(SplitButton sender, SplitButtonClickEventArgs args)
{
    if (noteModel is not null)
    {
        await noteModel.SaveAsync();
        Frame.Navigate(typeof(AllNotesPage), noteModel);
    }
}

处理 AllNotesPage 中的导航参数

AllNotesPage 中,您需要处理传入的导航参数(Note),并根据需要将其添加到 Notes 集合中或从中移除。

若要处理传入的导航参数,请重写 OnNavigatedTo 方法,如下所示。

// ↓ Add this. ↓
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (e.Parameter is Note note)
    {
        if (note.State == NoteState.Deleted)
        {
            notesModel.RemoveNote(note);
        }
        else if (!notesModel.Notes.Contains(note))
        {
            notesModel.AddNote(note);
        }
        // This navigation should be treated like a
        // back navigation, so clear the backstack.
        Frame.BackStack.Clear();
    }
}

现在,可以运行应用来了解这些更改的工作原理。 尝试添加新笔记、在笔记之间来回导航以及删除笔记。

在文档中了解详细信息:

后续步骤

恭喜! 你已完成 WinUI 说明第 2 部分 教程!

以下链接提供有关使用 WinUI 和 Windows 应用 SDK 创建应用的详细信息: