Resumen del capítulo 18. MVVM
Nota:
Este libro se publicó en la primavera de 2016 y no se ha actualizado desde entonces. Gran parte del libro sigue siendo útil, pero algunos de los materiales están anticuados y algunos temas ya no son completamente correctos o completos.
Una de las mejores formas de diseñar una aplicación es separar la interfaz de usuario del código subyacente, que a veces se denomina lógica de negocios. Existen varias técnicas, pero la que se adapta a los entornos basados en XAML se conoce como Modelo-Vista-Modelo de vista o MVVM.
Interrelaciones de MVVM
Una aplicación MVVM tiene tres niveles:
- Modelo proporciona datos subyacentes, a veces a través de archivos o accesos web.
- Vista es la interfaz de usuario o la capa de presentación, normalmente implementada en XAML.
- Modelo de vista conecta el Modelo y la Vista.
Modelo es independiente de Modelo de vista y Modelo de vista es independiente de Vista. Estas tres capas generalmente se conectan entre sí mediante los mecanismos siguientes:
En muchos programas más pequeños (e incluso más grandes), a menudo Modelo está ausente o su funcionalidad está integrada en Modelo de vista.
Modelos de vista y enlace de datos
Para interactuar con los enlaces de datos, un Modelo de vista debe ser capaz de informar a Vista del cambio de una propiedad en Modelo de vista. Para ello, Modelo de vista implementa la interfaz de INotifyPropertyChanged
en el espacio de nombres de System.ComponentModel
. Esto forma parte de .NET y no de Xamarin.Forms. (Por lo general, los Modelos de vista intentan mantener la independencia de la plataforma).
La interfaz INotifyPropertyChanged
declara un evento único denominado PropertyChanged
que indica la propiedad que ha cambiado.
Un reloj de Modelo de vista
DateTimeViewModel
en la biblioteca Xamarin.FormsBook.Toolkit define una propiedad de tipo DateTime
que cambia en función de un temporizador. La clase implementa INotifyPropertyChanged
y activa el evento PropertyChanged
cada vez que cambia la propiedad DateTime
.
En el ejemplo MvvmClock se crea una instancia de este Modelo de vista y se usan enlaces de datos al Modelo de vista para mostrar la información de fecha y hora actualizada.
Propiedades interactivas en un Modelo de vista
Las propiedades de un Modelo de vista pueden ser más interactivas, como se muestra por la clase SimpleMultiplierViewModel
, que forma parte del ejemplo SimpleMultiplier. Los enlaces de datos proporcionan los valores de multiplicando y multiplicador de dos elementos Slider
y muestran el producto con Label
. Sin embargo, puede realizar cambios extensivos en esta interfaz de usuario en XAML sin que se realicen cambios en el Modelo de vista ni en el archivo de código subyacente.
Un Modelo de vista de colores
ColorViewModel
en la biblioteca Xamarin.FormsBook.Toolkit integra los modelos de color RGB y HSL. Esto se muestra en el ejemplo HslSliders:
Optimización del Modelo de vista
El código de los Modelos de vista se puede simplificar mediante la definición de un método OnPropertyChanged
que use el atributo CallerMemberName
, que obtiene automáticamente el nombre de la propiedad que realiza la llamada. La clase ViewModelBase
de la biblioteca Xamarin.FormsBook.Toolkit lo hace y proporciona una clase base para ViewModels.
Interfaz de comandos
MVVM funciona con enlaces de datos, y los enlaces de datos funcionan con propiedades, por lo que MVVM parece ser deficiente cuando se trata de controlar un evento Clicked
de Button
o un evento Tapped
de TapGestureRecognizer
. Para permitir que los Modelos de vista controlen estos eventos, Xamarin.Forms admite la interfaz de comandos.
La interfaz de comandos se manifiesta en Button
con dos propiedades públicas:
Command
de tipoICommand
(definido en el espacio de nombresSystem.Windows.Input
)CommandParameter
de tipoObject
Para admitir la interfaz de comandos, un Modelo de vista debe definir una propiedad de tipo ICommand
que sea entonces un enlace de datos a la propiedad Command
de Button
. La interfaz ICommand
declara dos métodos y un evento:
- Un método
Execute
con un argumento de tipoobject
- Un método
CanExecute
con un argumento de tipoobject
que devuelvebool
- Un evento
CanExecuteChanged
Internamente, un Modelo de vista establece cada propiedad de tipo ICommand
en una instancia de una clase que implementa la interfaz ICommand
. A través del enlace de datos, Button
llama inicialmente al método CanExecute
y se deshabilita a sí mismo si el método devuelve false
. También establece un controlador para el evento CanExecuteChanged
y llama a CanExecute
cada vez que se desencadena ese evento. Si Button
está habilitado, llama al método Execute
cada vez que se hace clic en Button
.
Es posible que tenga algunos Modelos de vista que son anteriores a Xamarin.Forms, y que estos ya admitan la interfaz de comandos. En el caso de los nuevos Modelos de vista que se van a usar solo con Xamarin.Forms, Xamarin.Formsproporciona una clase Command
y una clase Command<T>
que implementa la interfaz ICommand
. El tipo genérico es el tipo del argumento para los métodos Execute
y CanExecute
.
Ejecuciones de método simples
En el ejemplo PowersOfThree se muestra cómo usar la interfaz de comandos en un Modelo de vista. La clase de PowersViewModel
define dos propiedades de tipo ICommand
y también define dos propiedades privadas que se pasan al constructor Command
más sencillo. El programa contiene enlaces de datos de este Modelo de vista a las propiedades Command
de dos elementos Button
.
Los elementos Button
se pueden reemplazar fácilmente por objetos TapGestureRecognizer
en XAML sin cambios de código.
Una calculadora, casi
En el ejemplo AddingMachine se usan los métodos Execute
y CanExecute
de ICommand
. Usa una clase AdderViewModel
en la biblioteca Xamarin.FormsBook.Toolkit. El Modelo de vista contiene seis propiedades de tipo ICommand
. Se inicializan desde el constructor Command
y el constructor Command
de Command
y el constructor Command<T>
de Command<T>
. Todas las claves numéricas del equipo que agrega están enlazadas a la propiedad que se inicializa con Command<T>
, y un argumento string
a Execute
y CanExecute
identifica la clave determinada.
Modelos de vista y el ciclo de vida de la aplicación
AdderViewModel
utilizado en el ejemplo AddingMachine también define dos métodos denominados SaveState
y RestoreState
. Se llama a estos métodos desde la aplicación cuando entra en suspensión y cuando se inicia de nuevo.