演習 - ビューモデルを使って選択を管理する
この演習では、人事のアプリの例から少し離れます。 代わりに、ムービーを一覧表示するアプリケーションを使用します。 アプリには、2 つのページと、いくつかの基本的なバインドを備えたビューモデルが既にあります。 その 2 つのページは、リスト ページと詳細ページです。 ここでは、ListView
と詳細ページで同じビューモデルのプロパティを使うように、選択ロジックを変更します。
サンプルのダウンロードと実行
Note
Windows から Android 上の .NET MAUI アプリを実行してデバッグすることを計画している場合は、演習コンテンツを C:\dev\ のような短いフォルダー パスにクローンするかダウンロードし、ビルドによって生成されるファイルがパスの最大長を超えないようにすることをお勧めします。
この演習モジュールを開始するにあたり、Movie List Sample プロジェクトをダウンロードします。 このプロジェクトでは、ムービーの一覧が表示されます。 ムービーをクリックすると、ムービーに関する詳細情報が表示された詳細ページに移動します。
- Movie List Sample プロジェクトをダウンロードして、一時フォルダーに展開します。
- part4-exercise1 フォルダーに移動し、MovieCatalog.sln ソリューションを開きます。
- プロジェクトをビルドして実行し、プロジェクトが動作することを確認します。 表示された画面に、ムービーの一覧が表示されます。 一覧表示されているいずれかのムービーを選択すると、アプリが詳細ページに移動します。
コードを確認する
数分かけてビューモデルとビューがどのように構造化されているかを調べます。 XAML とデータ バインディングに慣れている場合は、目新しいものはないはずですが、構造には MVVM パターンが使われています。
MovieListViewModel
は、アプリの全体的なビューモデルと、MoviesListPage
のビューモデルという 2 つの役割を受け持っています。 このビューモデルには、モデルから読み込まれたムービーの一覧が含まれています。これは、プロジェクトに含まれる json ファイルです。 もう 1 つのビューモデルは MovieViewModel
であり、1 つのムービーを表します。 これも、リスト ページの行にデータを提供することと、MovieDetailPage
の BindingContext
という 2 つの役割を受け持っています。
選択のサポートを追加する
MoviesListPage
は、アプリの実行時に最初に表示されるページです。 ページ上の ListView
は、ビューモデル MovieListViewModel
全体で提供される MovieViewModel
インスタンスのコレクションにバインドされます。 ビュー内のいずれかのムービーを選択すると、ItemTapped
イベントは MovieDetailPage
に移動し、ムービーである項目の BindingContext
をビューのコンストラクターに渡します。 MovieDetailPage
は、渡されたビューモデルをページの BindingContext
として設定します。
代わりに、MovieDetailPage
がアプリ全体のビューモデルから選択したムービーを読み取るようにアプリを更新しましょう。
ソリューション エクスプローラー ウィンドウで、ViewModels\MovieListViewModel.cs ファイルを開きます。
以下のコードを
MovieListViewModel
クラスに追加します。private MovieViewModel _selectedMovie; public MovieViewModel SelectedMovie { get => _selectedMovie; set => SetProperty(ref _selectedMovie, value); }
次に、Views\MoviesListPage.xaml ファイルを開きます。
ListView
要素を探して、SelectedItem
属性を追加します。<ListView ItemsSource="{Binding Movies}" SelectedItem="{Binding SelectedMovie, Mode=OneWayToSource}" Margin ... >
この属性は、リストの選択項目をビューモデルの新しいプロパティにバインドします。
ビュー Views\MoviesListPage.xaml.cs の分離コード ファイルを開きます。
ListView_ItemTapped
イベント ハンドラー コードを次のコードに置き換えます。private async void ListView_ItemTapped(object sender, ItemTappedEventArgs e) { await Navigation.PushAsync(new Views.MovieDetailPage()); }
MovieDetailPage
はコンストラクターでムービーを受け入れなくなりました。代わりに、新しいコンストラクターがアプリのメイン ビューモデルを読み取ります。Views\MovieDetailPage.xaml.cs ファイルを開き、コンストラクターを次のコードに変更します。
public MovieDetailPage() { BindingContext = App.MainViewModel.SelectedMovie; InitializeComponent(); }
このコードによって、選択したムービーにビューのバインディング コンテキストが設定されます。
アプリを実行し、コードが意図したとおりに動作することを確認します。