context c# wpf design-patterns mvvm

c# - mvvm context devexpress



Herencia MVVM Con Modelos Ver (4)

Creo que el problema aquí es que debería haber un ViewModel para cada Vista, y no un ViewModel para cada modelo.

La razón de esto es bastante obvia, ya que solo puede configurar un objeto para que sea el DataContext, ese objeto debería ser el ViewModel para esa Vista.

Me pregunto cómo abordar la herencia con los modelos de vista en el patrón MVVM. En mi solicitud tengo un modelo de datos que se parece a lo siguiente:

class CustomObject { public string Title { get; set; } } class CustomItem : CustomObject { public string Description { get; set; } } class CustomProduct : CustomItem { public double Price { get; set; } }

En mi solicitud tengo una clase ViewModelBase y luego iba a tener los siguientes modelos de vista:

  • CustomObjectViewModel
  • CustomItemViewModel
  • CustomProductViewModel

Una implementación aproximada del CustomObjectViewModel se asemejaría a lo siguiente:

class CustomObjectViewModel : ViewModelBase { private readonly CustomObject _customObject; public CustomObjectViewModel( CustomObject customObject ) { _customObject = customObject; } public string Title { // implementation excluded for brevity } }

Me parece lógico que mis modelos de vista se extiendan a sí mismos de la misma manera que lo hizo mi modelo (CustomItemViewModel extiende CustomObjectViewModel y así sucesivamente). Sin embargo, he notado que a medida que avanzo el árbol de herencia, iré agregando referencias adicionales al mismo objeto. Esto me parece excesivo y me preguntaba cómo abordar este problema y si era posible hacerlo mucho más limpio.


En general, le recomendaría que no tenga herencia entre diferentes clases de ViewModel , sino que las herede directamente de una clase base abstracta común.
Esto es para evitar la introducción de una complejidad innecesaria al contaminar las interfaces de las clases de ViewModel con miembros que provienen de una jerarquía superior, pero que no están totalmente cohesionados al propósito principal de la clase.
El acoplamiento que viene con la herencia probablemente también dificultará el cambio de una clase ViewModel sin afectar a ninguna de sus clases derivadas.

Si sus clases de ViewModel siempre harán referencia a un solo objeto Modelo, podría usar los genéricos para encapsular esta regla en la clase base:

public abstract class ViewModelBase<TModel> { private readonly TModel _dataObject; public CustomObjectViewModel(TModel dataObject) { _dataObject = dataObject; } protected TModel DataObject { get; } } public class CustomObjectViewModel : ViewModelBase<CustomObject> { public string Title { // implementation excluded for brevity } } public class CustomItemViewModel : ViewModelBase<CustomItem> { public string Title { // implementation excluded for brevity } public string Description { // implementation excluded for brevity } }


Me interesaría ver si hay una mejor respuesta para esto, pero cuando he tenido el mismo problema, siempre he incluido un reparto explícito del objeto como una propiedad privada:

class CustomObjectViewModel : ViewModelBase { protected readonly CustomObject CustomObject; public CustomObjectViewModel( CustomObject customObject ) { CustomObject = customObject; } public string Title { // implementation excluded for brevity } } class CustomItemViewModel : CustomObjectViewModel { protected CustomItem CustomItem { get { return (CustomItem)CustomObject; } } public CustomItemViewModel( CustomItem customItem ) :base(customItem) { } }

Funciona, y es lo mejor que he encontrado, pero nunca me ha parecido muy limpio.


Relacionado con el comentario anterior de Enrico. ViewModels no debe estar estrechamente acoplado a las vistas, debe ser al revés. Las vistas se deben acoplar libremente a los modelos de vista. Un ViewModel no debe conocer una vista, esto le permite probar un ViewModel de forma sencilla. Todas las interacciones entre Vistas con ViewModel deben implementarse a través de propiedades en ViewModel (ICommand propiedades para acciones y otras propiedades para enlace de datos).

Lo único que es cierto es que el ViewModel está estrechamente relacionado con el Modelo, por lo que el uso de los genéricos anteriores permite una gran cantidad de extensibilidad. Es el patrón que yo recomendaría.

Al proporcionar una clase de ViewModel que básicamente solo expone Propiedades, debería permitirle introducir eso en cualquier tipo de marco de presentación y aprovechar todo el código que ha usado anteriormente. En otras palabras, si se implementa correctamente, puede colocar su ensamblaje ViewModels en una aplicación MVC de ASP.NET y vincular la vista a las propiedades y no cambiar el código.

Un buen artículo sobre los conceptos básicos de MVVM es: este. Realmente creo que MVVM es lo mejor que hay para el desarrollo de IU. Obviamente, no todos podemos usarlo porque requiere crear una aplicación desde cero utilizando el enfoque de MVVM, pero cuando estás creando una nueva aplicación que no es un problema.

La única queja que tengo con ICommand es que está en la Asamblea PresentationCore, que es básicamente para WPF. Si Microsoft quisiera un acoplamiento suelto, debería estar en otro conjunto.