Exercise - Convert an event handler to a command
In this exercise, swap back to the "movie list" app you worked with in the previous exercise. This time, you'll convert the Delete menu's event handler to a command.
Download and run the sample
Note
If you are planning to run and debug your .NET MAUI apps on Android from Windows, it's best to clone or download the exercise content to a short folder path, such as C:\dev\, to avoid build-generated files exceeding the maximum path length.
To start this exercise module, download the Movie List Sample project. This project displays a list of movies. Clicking on a movie navigates to a detail page with more information about the movie.
- Download and extract the Movie List Sample project to a temporary folder.
- Navigate to the part6-exercise2 folder and open the MovieCatalog.sln solution.
- Build and run the project to make sure it works. On the screen displayed, you'll see a list of movies. Right-click on one of the movies listed and the app navigates to a detail page.
Examine the code
Open the MovieCatalog solution and open the Views\MovieListPage.xaml file. The ListView
presents an item for each movie in the bound Movies
collection. Each item defines a context menu to delete a movie:
<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>
When the menu item is clicked, the MenuItem_Clicked
is invoked and the movie is removed. The binding context of the menu item is the current movie, the MovieViewModel
class. But the code for removing a movie is on the app's main viewmodel MovieListViewModel
. The event handler considers this as it gets the menu item's binding context and sends it to the viewmodel's DeleteMovie
method:
private void MenuItem_Clicked(object sender, EventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ViewModels.MovieViewModel movie = (ViewModels.MovieViewModel)menuItem.BindingContext;
App.MainViewModel.DeleteMovie(movie);
}
Add a command
The first step in converting the event handler to a command is adding the command to the viewmodel. This command accepts a movie and removes it from the collection.
In the Solution Explorer window, open the ViewModels\MovieListViewModel.cs file.
Add the following property to the
MovieListViewModel
class:public ICommand DeleteMovieCommand { get; private set; }
Next, find the
MovieListViewModel
constructor and instantiate the command:public MovieListViewModel() { Movies = []; DeleteMovieCommand = new Command<MovieViewModel>(DeleteMovie); }
The
DeleteMovie
method already exists and accepts aMovieViewModel
parameter. The command wraps that method and exposes it on the viewmodel.Open the ViewModels\MoviesListPage.xaml file.
Update the
MenuItem
to binding theCommand
parameter to theDeleteMovieCommand
. Pass the current binding context as theCommandParameter
.<MenuItem Text="Delete" IsDestructive="True" Command="{Binding DeleteMovieCommand, Source={x:Static local:App.MainViewModel}}" CommandParameter="{Binding}" />
Notice that the
Clicked
event handler was removed from theMenuItem
.The
Source
of the binding context is set to the app's main viewmodel, just like the page itself is. The binding context of theMenuItem
remains the movie, and that's passed to theCommandParameter
.Open the code-behind file for the view, Views\MoviesListPage.xaml.cs, and remove the
MenuItem_Clicked
code.Run the app and right-click or long-press one of the movies, select Delete from the context menu. The movie is deleted from the list.