演習 - イベント ハンドラーをコマンドに変換する

完了

この演習では、前の演習で作業した "ムービー一覧" アプリに戻ります。 今回は、[削除] メニューのイベント ハンドラーをコマンドに変換します。

サンプルのダウンロードと実行

Note

Windows から Android 上の .NET MAUI アプリを実行してデバッグすることを計画している場合は、演習コンテンツを C:\dev\ のような短いフォルダー パスにクローンするかダウンロードし、ビルドによって生成されるファイルがパスの最大長を超えないようにすることをお勧めします。

この演習モジュールを開始するにあたり、Movie List Sample プロジェクトをダウンロードします。 このプロジェクトでは、ムービーの一覧が表示されます。 ムービーをクリックすると、ムービーに関する詳細情報が表示された詳細ページに移動します。

  1. Movie List Sample プロジェクトをダウンロードして、一時フォルダーに展開します。
  2. part6-exercise2 フォルダーに移動し、MovieCatalog.sln ソリューションを開きます。
  3. プロジェクトをビルドして実行し、プロジェクトが動作することを確認します。 表示された画面に、ムービーの一覧が表示されます。 一覧表示されているいずれかのムービーを右クリックすると、アプリが詳細ページに移動します。

コードを確認する

MovieCatalog ソリューションを開き、Views\MovieListPage.xaml ファイルを開きます。 ListView は、バインドされた Movies コレクション内の各ムービーの項目を表示します。 各項目によって、ムービーを削除するためのコンテキスト メニューが定義されます。

<ListView.ItemTemplate>
    <DataTemplate>
        <TextCell Text="{Binding Title}" x:DataType="vm:MovieViewModel">
            <TextCell.ContextActions>
                <MenuItem Text="Delete" IsDestructive="True" Clicked="MenuItem_Clicked" />
            </TextCell.ContextActions>
        </TextCell>
    </DataTemplate>
</ListView.ItemTemplate>

メニュー項目がクリックされると、MenuItem_Clicked が呼び出され、ムービーが削除されます。 メニュー項目のバインディング コンテキストは、現在のムービー、MovieViewModel クラスです。 ただし、ムービーを削除するためのコードは、アプリのメイン ビューモデル MovieListViewModel にあります。 イベント ハンドラーは、メニュー項目のバインド コンテキストを取得し、ビューモデルの DeleteMovie メソッドに送信するため、これを考慮します。

private void MenuItem_Clicked(object sender, EventArgs e)
{
    MenuItem menuItem = (MenuItem)sender;
    ViewModels.MovieViewModel movie = (ViewModels.MovieViewModel)menuItem.BindingContext;
    App.MainViewModel.DeleteMovie(movie);
}

コマンドを追加する

イベント ハンドラーをコマンドに変換する最初の手順は、コマンドをビューモデルに追加することです。 このコマンドはムービーを受け取り、コレクションから削除します。

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

  2. MovieListViewModel クラスに次のプロパティを追加します。

    public ICommand DeleteMovieCommand { get; private set; }
    
  3. 次に、MovieListViewModel コンストラクターを見つけて、コマンドをインスタンス化します。

    public MovieListViewModel()
    {
        Movies = [];
        DeleteMovieCommand = new Command<MovieViewModel>(DeleteMovie);
    }
    

    DeleteMovie メソッドは既に存在し、MovieViewModel パラメーターを受け取ります。 このコマンドは、そのメソッドをラップし、ビューモデルで公開します。

  4. ViewModels\MoviesListPage.xaml ファイルを開きます。

  5. Command パラメーターを DeleteMovieCommand にバインドするように MenuItem を更新します。 現在のバインディング コンテキストを CommandParameter として渡します。

    <MenuItem Text="Delete"
              IsDestructive="True"
              Command="{Binding DeleteMovieCommand, Source={x:Static local:App.MainViewModel}}"
              CommandParameter="{Binding}" />
    

    Clicked イベント ハンドラーが MenuItem から削除されていることに注意してください。

    バインディング コンテキストの Source は、ページ自体と同様に、アプリのメイン ビューモデルに設定されます。 MenuItem のバインディング コンテキストはムービーのままであり、CommandParameter に渡されます。

  6. ビュー Views\MoviesListPage.xaml.cs の分離コード ファイルを開き、MenuItem_Clicked コードを削除します。

  7. アプリを実行し、いずれかのムービーを右クリックまたは長押しして、コンテキスト メニューから [削除] を選択します。 ムービーがリストから削除されます。