Ejercicio: Conversión de un controlador de eventos en un comando

Completado

En este ejercicio, vuelva a cambiar a la aplicación "lista de películas" con la que ha trabajado en el ejercicio anterior. Esta vez, convertirá el controlador de eventos del menú Eliminar en un comando.

Descarga y ejecución del ejemplo

  1. Vaya a la carpeta part6-exercise2 y abra la solución MovieCatalog.sln en Visual Studio o la carpeta de Visual Studio Code.
  2. Compile y ejecute el proyecto para asegurarse de que funciona. En la pantalla que se muestra, verá una lista de películas. Haga clic con el botón derecho en una de las películas enumeradas y la aplicación navega a una página de detalles.

Examen del código

Abra la solución MovieCatalog y abra el archivo Views\MovieListPage.xaml. ListView presenta un elemento para cada película de la colección enlazada Movies. Cada elemento define un menú contextual para eliminar una película:

<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>

Cuando se hace clic en el elemento de menú, se invoca MenuItem_Clicked y se quita la película. El contexto de enlace del elemento de menú es la película actual, la clase MovieViewModel. Pero el código para quitar una película está en el modelo de vista principal MovieListViewModel de la aplicación. El controlador de eventos considera esto, ya que obtiene el contexto de enlace del elemento de menú y lo envía al método DeleteMovie del modelo de vista:

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

Adición de un comando

El primer paso para convertir el controlador de eventos en un comando es agregar el comando al modelo de vista. Este comando acepta una película y la quita de la colección.

  1. En la ventana Explorador de soluciones, abra el archivo ViewModels\MovieListViewModel.cs.

  2. Agregue la siguiente propiedad a la clase MovieListViewModel:

    public ICommand DeleteMovieCommand { get; private set; }
    
  3. A continuación, busque el constructor MovieListViewModel y cree una instancia del comando:

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

    El método DeleteMovie ya existe y acepta un parámetro MovieViewModel. El comando ajusta ese método y lo expone en el modelo de vista.

  4. Abra el archivo ViewModels\MoviesListPage.xaml.

  5. Actualice MenuItem para enlazar el parámetro Command a DeleteMovieCommand. Pase el contexto de enlace actual como CommandParameter.

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

    Observe que el controlador de eventos Clicked se quitó de MenuItem.

    El Source del contexto de enlace se establece en el modelo de vista principal de la aplicación, al igual que la propia página. El contexto de enlace de MenuItem permanece en la película y se pasa a CommandParameter.

  6. Abra el archivo de código subyacente para la vista, Views\MoviesListPage.xaml.cs y quite el código MenuItem_Clicked.

  7. Ejecute la aplicación y haga clic con el botón derecho o presione una de las películas, seleccione Eliminar en el menú contextual. La película se elimina de la lista.