演習 - ビューモデルを使って選択を管理する

完了

この演習では、人事アプリの例から少し離れます。 代わりに、映画を一覧表示するアプリケーションで作業をします。 アプリには、2 つのページと、いくつかの基本的なバインドを備えたビューモデルが既にあります。 その 2 つのページは、リスト ページと詳細ページです。 CollectionView と詳細ページで同じビューモデル プロパティが使用されるように、選択ロジックを変更します。

このモジュールでは、.NET 10.0 SDK を使用します。 任意のコマンド ターミナルで次のコマンドを実行して、.NET 10.0 がインストールされていることを確認します。

dotnet --list-sdks

次の例のような出力が表示されます。

9.0.100 [C:\Program Files\dotnet\sdk]
10.0.100 [C:\Program Files\dotnet\sdk]

10 で始まるバージョンが一覧に表示されていることを確実にします。 何も表示されていない場合、またはコマンドが見つからない場合は、 最新の .NET 10.0 SDK をインストールします。

スターター ソリューションを開く

  1. exercise repo をクローンまたはダウンロードします。
  2. part4-exercise1 フォルダーに移動し、MovieCatalog.sln ソリューションを開きます。
  3. プロジェクトをビルドして実行し、プロジェクトが動作することを確認します。 画面上に映画の一覧が表示されます。 一覧の中の映画を 1 つ選択すると、アプリは詳細ページに移動します。

コードを確認する

数分かけてビューモデルとビューがどのように構造化されているかを調べます。 Extensible Application Markup Language (XAML) とデータ バインディングに慣れている場合はどれも見慣れているはずですが、この構造では Model-View-ViewModel (MVVM) パターンが使用されています。

MovieListViewModel は、アプリの全体的なビューモデルと、MoviesListPage のビューモデルという 2 つの役割を受け持っています。 このビューモデルには、モデルから読み込まれたムービーの一覧が含まれています。これは、プロジェクトに含まれる json ファイルです。 もう 1 つのビューモデルは MovieViewModel であり、1 つのムービーを表します。 これも、リスト ページの行にデータを提供することと、BindingContextMovieDetailPage という 2 つの役割を受け持っています。

選択のサポートを追加する

MoviesListPage は、アプリの実行時に表示される最初のページです。 ページ上の CollectionView は、ビューモデル MovieViewModel 全体で提供される MovieListViewModel インスタンスのコレクションにバインドされます。 ビュー内のいずれかのムービーを選択すると、SelectionChanged イベントは MovieDetailPage に移動し、ムービーである項目の BindingContext をビューのコンストラクターに渡します。 MovieDetailPage は、渡されたビューモデルをページの BindingContext として設定します。

代わりに、MovieDetailPage がアプリ全体のビューモデルから選択したムービーを読み取るようにアプリを更新しましょう。

  1. ソリューション エクスプローラー ウィンドウで、ViewModels\MovieListViewModel.cs ファイルを開きます。

  2. 以下のコードを MovieListViewModel クラスに追加します。

    private MovieViewModel _selectedMovie;
    
    public MovieViewModel SelectedMovie
    {
        get => _selectedMovie;
        set => SetProperty(ref _selectedMovie, value);
    }
    
  3. 次に、Views\MoviesListPage.xaml ファイルを開きます。

  4. CollectionView要素を見つけて、SelectedItem属性を追加します。 また、 SelectionModeSingleに設定されていることを確認します。

    <CollectionView ItemsSource="{Binding Movies}" 
                    SelectedItem="{Binding SelectedMovie, Mode=OneWayToSource}" 
                    Margin="10" 
                    SelectionMode="Single"
                    SelectionChanged="CollectionView_SelectionChanged">
    

    この属性は、リストの選択項目をビューモデルの新しいプロパティにバインドします。

  5. ビュー Views\MoviesListPage.xaml.cs の分離コード ファイルを開きます。

  6. CollectionView_SelectionChanged イベント ハンドラーを見つけます。 以下のコードに置き換えます。

    private async void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.CurrentSelection.Count == 0)
            return;
    
        await Navigation.PushAsync(new Views.MovieDetailPage());
    
        // Deselect
        ((CollectionView)sender).SelectedItem = null;
    }
    

    MovieDetailPage はコンストラクターでムービーを受け入れなくなりました。代わりに、新しいコンストラクターがアプリのメイン ビューモデルを読み取ります。

  7. Views\MovieDetailPage.xaml.cs ファイルを開き、コンストラクターを次のコードに変更します。

    public MovieDetailPage()
    {
        BindingContext = App.MainViewModel.SelectedMovie;
        InitializeComponent();
    }
    

    このコードによって、選択したムービーにビューのバインディング コンテキストが設定されます。

  8. アプリを実行し、コードが意図したとおりに動作することを確認します。