Chinch: Framework para el desarrollo de aplicaciones con Model-View-ViewModel


Chinch es unframework para el desarrollo de aplicaciones utilizando Model-View-ViewModel, por lo que he visto en los artículos de codeproject del autor tiene muy buena pinta, más información aqui

Los artículos de codeproject:

http://www.codeproject.com/KB/WPF/Cinch.aspx

http://www.codeproject.com/KB/WPF/CinchII.aspx

http://www.codeproject.com/KB/WPF/CinchIII.aspx

http://www.codeproject.com/KB/WPF/CinchIV.aspx

http://www.codeproject.com/KB/WPF/CinchV.aspx

http://www.codeproject.com/KB/WPF/CinchVI.aspx

Model-View-ViewModel (links)


    Buscando más información sobre el patrón Model-View-ViewMode he encontrado 2 links interesantes

Pattern Model-View-ViewModel, INotifyPropertyChanged, Static Reflection e Extension methods ( en italiano )

El autor plantea una solución para hacer que las notificaciones de cambios en los valores de las propiedades se haga a través de un método de extensión de Expression<Func<T>> en lugar de con cadenas de texto (con lo que en tiempo de compilación dará error si la propiedad no es válida).

A Master-Detail ViewModel ( en inglés )

El autor plantea una solución para implementar un ViewModel maestrodetalle.

Model-View-ViewModel Template para Visual Studio 2008


Disponible para descarga aquí.

Incluye:

  • Una plantilla para Visual Studio 2008 (Soporta la versión express)
  • Documentación
  • Una introducción al patrón Model-View-ViewModel
  • Una guía de uso de la plantilla
  • Un proyecto de ejemplo ( un cliente de mensajería instantánea por lo que he visto) a modo de  demostración del patrón.

Anuncio original visto aquí.

Model-View-ViewModel maestro detalle (II)


Finalmente para implementar el borrado de una “fila” de un detalle, he implementado una nueva clase MasterDetailViewModel, que deriva de la clase ViewModel que ya tenia implementada.

Las vistas en las que vayan a ser maestro-detalle deberán implementar el ViewMode derivando de esta clase.

La clase tiene dos propiedades nuevas

· CurrentDetailName. Que indica el nombre del detalle que está activo en la vista ( deberá coincidir con el nombre de una propiedad de la entidad asociada al ViewModel.

· CurrentItem. Que tiene el objeto que esta actualmente seleccionado en el detalle.

   1: public string CurrentDetailName
   2: {
   3:     get { return this.currentDetailName; }
   4:     set
   5:     {
   6:         if (this.currentDetailName != value)
   7:         {
   8:             this.currentDetailName = value;
   9:             this.UpdateAllowedUserActions();
  10:         }
  11:     }
  12: }
  13:  
  14: public object CurrentItem
  15: {
  16:     get { return this.currentItem; }
  17:     set 
  18:     {
  19:         if (this.currentItem != value)
  20:         {
  21:             this.currentItem = value;
  22:             this.UpdateAllowedUserActions();
  23:         }
  24:     }
  25: }

Además sobreescribe dos métodos de ViewModel, para poder activar el botón de borrar de la barra de herramientas cuando estamos en edición y hay un detalle activo y otro para realizar el borrado.

   1: protected override bool CanDelete(object obj)
   2: {
   3:     bool canDelete = false;
   4:  
   5:     if (this.ViewModelState == ViewModelStateType.Default)
   6:     {
   7:         canDelete = base.CanAddNew(obj);
   8:     }
   9:     else
  10:     {
  11:         canDelete = (this.DeleteCommand.IsActive && 
  12:             !String.IsNullOrEmpty(this.CurrentDetailName) &&
  13:             this.CurrentItem != null);
  14:     }
  15:  
  16:     return canDelete;
  17: }
  18:  
  19: protected override void Delete(object obj)
  20: {
  21:     if (this.ViewModelState == ViewModelStateType.Default)
  22:     {
  23:         base.Delete(obj);
  24:     }
  25:     else
  26:     {
  27:         // Get the detail property info
  28:         PropertyInfo pi = this.DataModel.GetType().GetProperty(currentDetailName);
  29:         Debug.Assert(pi != null, String.Format("Detail {0} not found", currentDetailName));
  30:  
  31:         // Get the detail property value
  32:         object detail = pi.GetValue(this.DataModel, null);
  33:         Debug.Assert(pi != null, String.Format("Detail {0} not found", currentDetailName));
  34:         Debug.Assert(detail is IBindingList, String.Format("Detail {0} doesn't implement IBindingList", currentDetailName));
  35:  
  36:         IBindingList detailList = (IBindingList)detail;
  37:  
  38:         // Add a new entity to the detail object and set it as the current item
  39:         detailList.Remove(this.CurrentItem);
  40:     }
  41: }

En mi caso el detalle se va a mostrar siempre en un Grid, que, por el momento al menos, es la versión Express de el DataGrid de Xceed.

La solución es la más sencilla y posiblemente no es la ideal, pero hasta que encuentre una mejor me vale.

Por el momento sólo tiene 2 pegas.

1. Que necesita código en la vista para actualizar el nombre del detalle que está activo, por ejemplo:

   1: private void DataGridCambios_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
   2: {
   3:     if (Convert.ToBoolean(e.NewValue))
   4:     {
   5:         this.ViewModel.CurrentDetailName = "Cambios";
   6:     }
   7:     else
   8:     {
   9:         this.ViewModel.CurrentDetailName = "";
  10:     }
  11: }

2. Que al realizar el borrado el Grid está perdiendo el foco, cosa que resulta bastante molesta, tendré que ver si tengo alguna forma de solventarlo jejeje