ナビゲーション パラメーターとしてメモを渡す

NoteStateが設定されたので、ナビゲーションを更新して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

次に、ClickのイベントNotePage.xaml.cs削除ボタンのコードを変更します。 メモを削除して戻る代わりに、ノートの状態を確認します。

  • 状態が Unset されている場合 (つまり、メモが新しく作成され、編集が行われず、保存されていません)、戻るだけです。 メモをパラメーターとして渡す必要はありません。
  • それ以外の場合は、ファイル システムからメモ ファイルを削除し、ナビゲーション パラメーターとして Note オブジェクトを渡します。 その後、AllNotesPageDeleted 状態の 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);
        }
    }
}

保存して閉じる

現在、ユーザーはノートを保存するためにクリックし、戻る矢印をクリックしてノート ページを閉じ、ノート コレクションに戻る必要があります。 このエクスペリエンスは、ユーザーが 1 回のクリックでメモを保存して閉じることで改善できます。 これを行うには、[保存] ボタンを、保存のみを行うドロップダウン オプション付きの [保存して閉じる] 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 を使用したアプリの作成の詳細については、次のリンクを参照してください。