ナビゲーション キャッシュと変更通知

最初の手順では、行う必要がある変更の基本的なセットアップを行います。

  • ナビゲーション キャッシュを有効にします。
  • Note.Text プロパティのプロパティ変更通知を実装します。

完了したら、アプリの他の部分を調整して、これらの変更を処理します。

Tip

このチュートリアルの完成したコードは、WinUI Notes パート 2 の GitHub リポジトリからダウンロードまたは表示できます。 プロジェクトの始点と終点の違いを確認するには、パート 2 の更新というコミットを参照してください。

NavigationCacheMode を有効にする

既定では、ナビゲーションが行われるたびに、新しい Page インスタンスが既定値で作成されます。 WinUI Notes アプリでは、すべてのnotesModel インスタンスを格納するNoteも作成されます。

AllNotesPage.xamlで、NavigationCacheModeEnabled (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">

今すぐアプリを実行すると、この変更の副作用がいくつかあります。

  1. 既存のノートを編集しても、戻るときにすべてのノート ページに変更が反映されません。
  2. 新しいメモを作成して保存しても、戻るときにすべてのノートの一覧に表示されません。
  3. 既存のノートを削除しても、戻るときにすべてのノートの一覧から削除されません。

次に、これらの問題を修正します。

詳細については、次のドキュメントを参照してください。

INotifyPropertyChanged を実装する

既存のメモを編集して保存すると、変更はファイル システムに保存されますが、変更はすべてのノートリストに反映されません。 これは、 Note クラスは、 TextBoxNote テキストに接続するデータ バインディングに更新が発生したことを通知しないためです。 この通知を行うには、Note クラスがそのINotifyPropertyChanged プロパティのText インターフェイスを実装する必要があります。

Note

WinUI には Microsoft.UI.Xaml.Data.INotifyPropertyChanged インターフェイスが含まれています。 これは、.NETを使用しない C++ アプリでのみ使用されます。

.NETで作成された C# アプリでは、代わりに System.ComponentModel.INotifyPropertyChanged インターフェイスが使用されます

INotifyPropertyChangedの実装は、セット パターンに従います。

  1. 必要な名前空間 using ステートメントを追加します。

    // ↓ Add this. ↓
    using System.ComponentModel
    using System.Runtime.CompilerServices
    
  2. INotifyPropertyChangedを実装します。 Note クラスがこのインターフェイスを実装するようになりました。

    // ↓ Update this. ↓
    public class Note : INotifyPropertyChanged
    
  3. _text プロパティのバッキング フィールド (Text) を作成します。

    // ↓ Delete this. ↓
    // public string Text { get; set; } = string.Empty;
    
    // ↓ Add this. ↓
    private string _text = string.Empty;
    
  4. プロパティ変更通知で getter/setter パターンを使用するように、 Text プロパティを変更します。

    // ↓ Add this. ↓
    public string Text
    {
        get => _text;
        set
        {
            if (_text != value)
            {
                _text = value;
                OnPropertyChanged();
            }
        }
    }
    
  5. インターフェイスに必要な INotifyPropertyChanged イベントを追加します。

    // ↓ Add this. ↓
    public event PropertyChangedEventHandler? PropertyChanged;
    
  6. 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}の一般的な間違いは、BindingModeまたはOneWayが必要な場合は、既定のTwoWayを忘れて変更することです)。

Name Description
OneTime バインディングが作成された場合にのみ、ターゲット プロパティを更新します。 {x:Bind}の既定値。
OneWay バインディングの作成時にターゲット プロパティを更新します。 ソース オブジェクトに対する変更は、ターゲットにも反映できます。
TwoWay いずれかの変更時に、ターゲット オブジェクトまたはソース オブジェクトを更新します。 バインディングが作成されると、ターゲット プロパティがソースから更新されます。

AllNotesPage.xamlで、Page.ResourcesNoteItemTemplateを見つけます。 次に、テンプレートで、TextBlock プロパティにバインドされているTextを見つけます。 OneWay バインド モードを使用するようにバインディングを更新します。

// ↓ Update this. ↓              ↓    ↓
<TextBlock Text="{x:Bind Text, Mode=OneWay}"
           Margin="4" TextWrapping="Wrap"
           TextTrimming="WordEllipsis"/>

ユーザーはTextBlock内のテキストを更新できないため、ソース (OneWay) からターゲット (Note.Text) へのTextBlock.Text バインディングのみが必要です。

詳細については、次のドキュメントを参照してください。