Archive

Posts Tagged ‘WPF’

MVVM Light Toolkit desde cero (paso 5)

August 2nd, 2011 3 comments

En este quinto artículo de la serie acerca del patrón arquitectural Model-View-ViewModel veremos lo concerniente al “View” ó Vista ó Interfaz de usuario.

El toolkit nos ha creado una clase llamada ViewModelLocator.cs que lo que permite es que la Vista (View.xaml) sepa a cual ViewModel estará enlazada. exploremos un poco esta clase.

En los comentarios iniciales de esta clase se destaca lo siguiente:

Esto nos da una buena pista acerca de lo que el Toolkit provee para agregar ViewModels a este localizador, nos está diciendo que utilicemos el snippet mvvmlocatorproperty y eso es lo que vamos a hacer.

colapsemos todo el código que por omisión se crea, y seguidamente a la declaración de la clase, después de :

vamos a crear una #region Puesto ViewModel y adentro de la región escribimos el snippet mvvmlocatorproperty y la tecla TAB para generar el código contenido en el snippet del toolkit, el cursor se ubica en ViewModelType, reemplazamos por PuestoViewModel que es la case que creamos en el paso 4 luego TAB para que el cursor se ubique en _viewModelPropertyName, reemplazamos por _puestoViewModel y luego TAB para que el cursor se ubique en el comentario /// Gets the ViewModelPropertyName property reemplazamos por PuestoViewModel y luego TAB. Con estos sencillos pasos, hemos creado lo necesario para que el Locator pueda enlazar el ViewModel con la Vista desde el código xaml.

Hay otras formas de enlazar la Vista y el ViewModel que podrían parecer mucho mas sencillas y de hecho lo son, pero el locator nos brindará una gran ayuda cuando estemos elaborando interfaces de usuario mas complejas que requieran la utilización de Microsoft Expression Blend. En la vista de Empleados no utilizaremos el locator para ver otra forma distinta de enlazar estos componentes de nuestra arquitectura.

Como se puede apreciar ya existe un método public static void CleanUp() en el código creado por omisión en el locator, y ahora hemos ingresado otro igual cuando creamos el código para el PuestoViewModel, así que tenemos dos. Copiemos el llamado que se hace en el CleanUp de PuestoViewModel al método ClearPuestoViewModel(); y peguémoslo en el otro método CleanUp seguidamente de ClearMain(); y luego eliminemos el método CleanUp que se generó para PuestoViewModel

  1. public static void Cleanup()
  2.         {
  3.             ClearMain();
  4.             ClearPuestoViewModel();
  5.         }

 

Al final, el código en el locator para localizar el ViewModel de Puesto es el siguiente:

  1. #region Puesto ViewModel
  2.  
  3.         private static PuestoViewModel _puestoViewModel;
  4.  
  5.         /// <summary>
  6.         /// Gets the PuestoViewModel property.
  7.         /// </summary>
  8.         public static PuestoViewModel PuestoViewModelStatic
  9.         {
  10.             get
  11.             {
  12.                 if (_puestoViewModel == null)
  13.                 {
  14.                     CreatePuestoViewModel();
  15.                 }
  16.  
  17.                 return _puestoViewModel;
  18.             }
  19.         }
  20.  
  21.         /// <summary>
  22.         /// Gets the PuestoViewModel property.
  23.         /// </summary>
  24.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
  25.             "CA1822:MarkMembersAsStatic",
  26.             Justification = "This non-static member is needed for data binding purposes.")]
  27.         public PuestoViewModel PuestoViewModel
  28.         {
  29.             get
  30.             {
  31.                 return PuestoViewModelStatic;
  32.             }
  33.         }
  34.  
  35.         /// <summary>
  36.         /// Provides a deterministic way to delete the PuestoViewModel property.
  37.         /// </summary>
  38.         public static void ClearPuestoViewModel()
  39.         {
  40.             _puestoViewModel.Cleanup();
  41.             _puestoViewModel = null;
  42.         }
  43.  
  44.         /// <summary>
  45.         /// Provides a deterministic way to create the PuestoViewModel property.
  46.         /// </summary>
  47.         public static void CreatePuestoViewModel()
  48.         {
  49.             if (_puestoViewModel == null)
  50.             {
  51.                 _puestoViewModel = new PuestoViewModel();
  52.             }
  53.         }
  54.  
  55.         #endregion

 

ubicados en el proyecto Empleados.WPF damos clic derecho y seleccionamos Add / New Folder, al folder recién creado la daremos el nombre de “View” ya que aquí es donde residirán todas nuestras vistas ó pantallas. ubicados en el folder View, damos clic derecho y seleccionamos Add / New Item

PuestoView

seleccionamos el tipo MvvmView (WPF) y le damos el nombre PuestoView.xaml a nuestra vista

el código Xaml generado muestra lo siguiente:

  1. <Window x:Class="Empleados.WPF.View.PuestoView"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.         mc:Ignorable="d"
  7.         DataContext="{Binding ViewModelName, Source={StaticResource Locator}}">
  8.  
  9.     <Grid>
  10.     </Grid>
  11. </Window>

debemos reemplazar en la propiedad DataContext la palabra ViewModelName, y colocar PuestoViewModel, que lo que hará es buscar una propiedad que se llame así en el locator utilizando un recurso estático que está declarado en el código xaml del archivo App.xaml en donde se le indica cual es la clase “Locator“ en nuestro caso ViewModelLocator. Este es el código de App.xaml

  1. <Application x:Class="Empleados.WPF.App"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:vm="clr-namespace:Empleados.WPF.ViewModel"
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  7.              StartupUri="MainWindow.xaml"
  8.              mc:Ignorable="d">
  9.    
  10.     <Application.Resources>
  11.         <!–Global View Model Locator–>
  12.         <vm:ViewModelLocator x:Key="Locator"
  13.                              d:IsDataSource="True" />
  14.     </Application.Resources>
  15.    
  16. </Application>

 

Con estos sencillos pasos ya la Vista tiene conocimiento de cual es su ViewModel y los controles que vayamos a incorporar en nuestra vista podrán enlazarse a las propiedades y comandos que hemos creado en el ViewModel. En modo de diseño crearemos la interfaz que se encargará de dar mantenimiento a puestos, haremos una interfaz muy sencilla ya que el objetivo de los artículos no está centrado en la UI (User Interface) y UX (User Experience), temas que por supuesto cubriré en futuros post con el uso de la herramienta Microsoft Expression Blend, pero por ahora diseñemos algo básico que trabaje con los componentes que hemos venido desarrollando en nuestra arquitectura.

Comencemos por indicar en nuestro código xaml cuales son las dimensiones en modo de diseño con las que queremos trabajar, d:DesignWith=”600” d:DesignHeight=”400” y donde queremos que inicialmente se presente la pantalla WindowStartupLocation=”CenterScreen” además indiquemos las dimensiones de alto y ancho de la pantalla cuando esté en modo de ejecución, With=”600” Height=”400”, además del título de la ventana agregando la propiedad Title=”Gestión de Puestos”, Adicionalmente debemos agregar los siguientes namespaces a nuestro código xaml

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"

PuestoView1

seleccionamos el Grid en el código xaml, vamos a crear varios rows que nos permitan acomodar los controles con los que vamos a trabajar, una vez seleccionado el Grid en la vista de diseño veremos que alrededor se ve de color celeste, indicando que tenemos seleccionado el Grid, vamos a hacer clic en la barra lateral izquierda, dos veces en distintas ubicaciones de la barra cada vez, con la finalidad de crear rows en nuestro Grid. como se muestra en las siguientes imágenes.

PuestoView1

PuestoView2

ajustamos las dimensiones de altura “Height” en nuestro código xaml para que queden con las dimensiones que se muestra en la imagen, y procedemos a agregar botones, textblocks, textbox, y DataGrid desde el toolbox, como se ve en la imagen a continuación

PuestoView3

Ahora vamos a ir enlazando cada control con su respectiva propiedad o comando del ViewModel, comencemos por los botones.

Seleccionamos el botón Nuevo y en la ventana de propiedades buscamos la propiedad Command y damos clic en Propiedades Avanzadas para acceder al menú contextual y luego seleccionar la opción Apply Data Binding

New

En la ventana siguiente podremos observar las propiedades y comandos que hemos codificado en nuestro ViewModel, recordemos que ya la vista conoce cual es su ViewModel, seleccionamos con doble clic NewCommand en la sección de Path

New2

De la misma forma haremos con los siguientes botones, seleccionando SaveCommand y DeleteCommand en cada caso. Continuamos con el textbox de descripción, de igual forma pero ahora en la propiedad Text del control seleccionamos Propiedades Avanzadas y Apply Data Binding, seleccionamos la propiedad “Descripcion” de nuestro ViewModel y ahí mismo en la ventana de Binding, abrimos la sección de Options y en UpdateSourceTrigger seleccionamos la opción PropertyChanged. Esta opción nos garantiza la correcta comunicación entre el ViewModel y el View, ya sea que se modifique la propiedad en el ViewModel (por que se consultó un puesto ó se limpió la propiedad) ó que se digite información en el textbox, el disparador de actualización será un cambio en la propiedad.

SourceTrigger

Por último seguimos con el DataGrid y en la propiedad ItemsSource seguimos el mismo proceso para aplicar el data binding, en este caso seleccionamos la propiedad de tipo ObservableCollection ListaPuestos y en Options seleccionamos igual que en el caso anterior la opción PropertyChanged en UpdateSourceTrigger, le indicamos al DataGrid que que las columnas serán generadas por nosotros, quitamos el check de AutoGenerateColumns de modo que en el código xaml quede AutoGenerateColumns=”False”.

Vamos a agregar las columnas necesarias así que buscamos la propiedad Columns en la ventana de propiedades y hacemos clic en los puntos suspensivos “…” que indican “Edit items in this collection”, en el Collection Editor:Columns nos aseguramos de que esté seleccionada la opción DataGridTextColumn y damos clic en Add para agregar una nueva columna, en las propiedades de la nueva columna modificamos los valores de IsReadOnly, Header, Width y Binding, y específicamente en esta última propiedad aplicamos el mismo mecanismo que en los anteriores controles para enlazar la propiedad Descripción tal y como se muestra en las siguientes imágenes.

New Column

NewColumn2

Al final damos clic en OK para aceptar los cambios.

Inmediatamente después de la declaración de las columnas en el código xaml y antes de cerrar el DataGrid insertamos el siguiente código:

  1. <i:Interaction.Triggers>
  2.                 <i:EventTrigger
  3.                     EventName="SelectionChanged">
  4.                     <cmd:EventToCommand
  5.                         Command="{Binding SelectionChangedCommand, Mode=OneWay}"
  6.                         CommandParameter="{Binding SelectedItem, ElementName=dataGrid1}" />
  7.                 </i:EventTrigger>
  8.             </i:Interaction.Triggers>

 

Este código es una funcionalidad provista por el Toolkit y lo que permite es capturar un evento determinado e indicar a cual comando en el ViewModel estará enlazado “EventToCommand” pasando por parámetro en este caso el ítem seleccionado “SelectedItem”, para nuestro caso el comando al cual estará enlazado será SelectionChangedCommand, RelayCommand escrito en nuestro ViewModel.

Lo último que tenemos que hacer para desplegar nuestra aplicación es indicar cual será el “View” que se desplegará, y eso lo hacemos modificando el archivo App.xaml en la propiedad StartupUri=”View/PuestoView.xaml”

startupuri

Ejecutamos con F5, La aplicación deberá verse de la siguiente forma:

GestionPuestos

Con esto concluyo el mantenimiento de Puestos, en el siguiente artículo veremos el mantenimiento de Empleados y estaré omitiendo algunos de los pasos que ya hemos visto aquí concentrándome en las particularidades que tenga ese mantenimiento respecto de este que desarrollamos. Gracias y nos vemos en el próximo!. Si desea conocer más acerca del autor de estos artículos puede acceder a su blog personal en la siguiente dirección http://zitrodan.wordpress.com/

MVVM Light Toolkit desde cero (paso 4)

August 2nd, 2011 No comments

Esta es la cuarta entrega de la serie acerca del patrón arquitectural Model – View – ViewModel y específicamente su implementación utilizando MVVM Light Toolkit. En las tres primeras entregas se cubrieron los temas de la instalación, la creación de la base de datos, el modelo utilizando ADO.NET Entity Framework y las clases de lógica de acceso a datos (modelo) utilizando LINQ to Entities. Con el paso 4 pretendo mostrar la implementación del componente “ViewModel” de la arquitectura.

Ubicados en el proyecto Empleados.WPF y en la carpeta ViewModel damos clic derecho y Add New Item…, en el árbol de Installed Templates expandimos WPF y seleccionamos Mvvm, a la derecha se mostrarán las plantillas instaladas por MMVM Light Toolkit. Seleccionamos MvvmViewModel (WPF) y el nombre que le daremos será PuestoViewModel.cs y luego clic en Add.

PuestoViewModelCreation

Esto nos creará una clase que se encargará de interactuar con la Vista (View) ó interfaz de usuario. él código creado por omisión en la clase es el siguiente :

  1. using GalaSoft.MvvmLight;
  2. namespace Empleados.WPF.ViewModel
  3. {
  4.     ///<summary>
  5.     /// This class contains properties that a View can data bind to.
  6.     ///<para>
  7.     /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
  8.     ///</para>
  9.     ///<para>
  10.     /// You can also use Blend to data bind with the tool’s support.
  11.     ///</para>
  12.     ///<para>
  13.     /// See http://www.galasoft.ch/mvvm/getstarted
  14.     ///</para>
  15.     ///</summary>
  16.     publicclassPuestoViewModel : ViewModelBase
  17.     {
  18.         ///<summary>
  19.         /// Initializes a new instance of the PuestoViewModel class.
  20.         ///</summary>
  21.         public PuestoViewModel()
  22.         {
  23.             ////if (IsInDesignMode)
  24.             ////{
  25.             ////    // Code runs in Blend –> create design time data.
  26.             ////}
  27.             ////else
  28.             ////{
  29.             ////    // Code runs “for real”: Connect to service, etc…
  30.             ////}
  31.         }
  32.         ////public override void Cleanup()
  33.         ////{
  34.         ////    // Clean own resources if needed
  35.         ////    base.Cleanup();
  36.         ////}
  37.     }
  38. }

Algunos comentarios en el código nos dan la pista de lo que podemos realizar a partir de este momento con la clase PuestoViewModel, el primero es el uso del “Snippet” ó fragmento de código previamente escrito en el Toolkit, “mvvminpc” model-view-viewmodel INotify Property Changed, que nos facilitará la creación de las propiedades que estarán enlazadas (binding) a la vista, luego en el constructor de la clase viene codificado y comentado la sentencia if (IsInDesignMode) que lo que pretende es facilitarnos la codificación si estuviésemos utilizando Microsoft Expression Blend y datos de prueba para ejecutar la aplicación ó si por el contrario estamos utilizando (como es nuestro caso) código real que se conecta a un servicio web ó base de datos para obtener la información.

podemos borrar todos los comentarios por omisión en el código para que nos quede mas limpio y proceder a la creación de las propiedades del ViewModel que estarán enlazadas a la Vista. Inmediatamente después de la declaración de la clase creamos una región donde agruparemos todas las propiedades #region ViewModel Properties, dentro de esta región crearemos regiones para cada una de las propiedades comenzando con #region ViewModel Property : Descripción (la descripción del puesto) dentro de esta primer región escribimos el snippet mvvminpc y luego la tecla TAB para que se genere el fragmento de código correspondiente al snippet. El fragmento de código generado se verá como el siguiente:

  1. #region ViewModel Property : Descripcion
  2.         ///<summary>
  3.         /// The <see cref=“MyProperty” /> property’s name.
  4.         ///</summary>
  5.         publicconststring MyPropertyPropertyName =“MyProperty”;
  6.         privatebool _myProperty =false;
  7.         ///<summary>
  8.         /// Gets the MyProperty property.
  9.         ///TODO Update documentation:
  10.         /// Changes to that property’s value raise the PropertyChanged event.
  11.         /// This property’s value is broadcasted by the Messenger’s default instance when it changes.
  12.         ///</summary>
  13.         publicbool MyProperty
  14.         {
  15.             get
  16.             {
  17.                 return _myProperty;
  18.             }
  19.             set
  20.             {
  21.                 if (_myProperty ==value)
  22.                 {
  23.                     return;
  24.                 }
  25.                 var oldValue = _myProperty;
  26.                 _myProperty =value;
  27.                 // Remove one of the two calls below
  28.                 thrownewNotImplementedException();
  29.                 // Update bindings, no broadcast
  30.                 RaisePropertyChanged(MyPropertyPropertyName);
  31.                 // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
  32.                 RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
  33.             }
  34.         }

El cursor se ubicará Inicialmente en MyProperty aquí sobrescribimos reemplazando por la palabra Descripcion que es el nombre de nuestra propiedad y luego damos la tecla TAB para que el cursor se ubique en la siguiente sección del fragmento de código que debemos reemplazar que es el tipo de la propiedad, por omisión el snippet genera de tipo bool, reemplacemos por string, luego TAB para ubicarnos en el atributo _myProperty y modificarlo por _descripcion y nuevamente TAB para ubicarnos en el valor inicial del atributo cuyo valor por omisión es false, lo reemplazamos por string.Empty.

También deberemos eliminar algunas líneas de código que genera el snippet como se ve en la siguiente imagen:

Inpc

el snippet permite implementar cualquiera de dos modalidades para la notificación de cambios, la primera con el comentario // Update bindings, no broadcast es la que utilizaremos por omisión, la segunda opción permite además de notificar cambios de la propiedad a la vista, transmitir su valor mediante Messenging ó mensajería hacía otros ViewModel, por ejemplo podríamos necesitar que un ViewModel transmita el código de puesto hacia otro ViewModel que estuviera enlazado a una vista que nos muestre todos los empleados ligados a ese puesto, como una pantalla de consulta emergente, pero el tema de mensajería será tema de otro post, por el momento eliminemos lo que está marcado en color rojo y de igual forma con cualquier otra propiedad que vayamos a crear.

Con estos sencillos pasos ya tenemos nuestra primer propiedad que implementa la interface INotifyPropertyChanged (heredada de ViewModelBase) y que notificará a nuestro ViewModel de cambios en la Vista y viceversa, notificará a la vista cuando cambiemos el valor de la propiedad. El término notificar no es mas que actualizar la Vista (según el tipo de control que estemos utilizando, Label, TexBox, TextBlock, etc) ó el valor de la propiedad en el ViewModel. La propiedad deberá verse como sigue:

  1. #region ViewModel Property : Descripcion
  2.         ///<summary>
  3.         /// The <see cref=“Descripcion” /> property’s name.
  4.         ///</summary>
  5.         publicconststring DescripcionPropertyName =“Descripcion”;
  6.         privatestring _descripcion =string.Empty;
  7.         publicstring Descripcion
  8.         {
  9.             get
  10.             {
  11.                 return _descripcion;
  12.             }
  13.             set
  14.             {
  15.                 if (_descripcion ==value) return;
  16.                 _descripcion =value;
  17.                 // Update bindings, no broadcast
  18.                 RaisePropertyChanged(DescripcionPropertyName);
  19.             }
  20.         }

Colapsamos la region de la recién creada propiedad y continuamos con la siguiente que será una propiedad que nos permitirá almacenar en memoria el registro completo de algún puesto que sea seleccionado de una lista en la Vista, con lista me refiero a algún DataGrid, ó ListBox donde despleguemos los registros de puestos que se vayan creando ó que sean retornados desde la base de datos.

Para continuar asegurémonos de incluir el siguiente namespace using Empleados.WPF.Model

Creamos una nueva región siempre dentro de la región (#region ViewModel Properties) a la que llamaremos #region ViewModel Property : CurrentPuesto y dentro de esta el snippet mvvminpc para generar el fragmento de código correspondiente; seguimos los mismos pasos como en la propiedad creada anteriormente, al final nuestra propiedad deberá verse como sigue

  1. #region ViewModel Property : CurrentPuesto
  2.         ///<summary>
  3.         /// The <see cref=“CurrentPuesto” /> property’s name.
  4.         ///</summary>
  5.         publicconststring CurrentPuestoPropertyName =“CurrentPuesto”;
  6.         privatePuestoModel _currentPuesto;
  7.         publicPuestoModel CurrentPuesto
  8.         {
  9.             get
  10.             {
  11.                 return _currentPuesto;
  12.             }
  13.             set
  14.             {
  15.                 if (_currentPuesto ==value) return;
  16.                 _currentPuesto =value;
  17.                 // Update bindings, no broadcast
  18.                 RaisePropertyChanged(CurrentPuestoPropertyName);
  19.             }
  20.         }

Para la siguiente propiedad incluimos el namespace using System.Collections.ObjectModel ya que esta propiedad corresponderá a una lista ObservableCollection de objetos de tipo PuestoModel. Este tipo de lista nos permitirá notificar a la Vista cuando un nuevo objeto de tipo PuestoModel sea agregado a la colección. Por ejemplo, si desplegamos los puestos creados en un DataGrid, y este DataGrid está enlazado por medio de Binding a la colección de objetos (ObservableCollection) en el ViewModel, cuando agreguemos un nuevo objeto a la colección el DataGrid se actualizará automáticamente.

La propiedad deberá verse como sigue:

  1. #region ViewModel Property : ListaPuestos
  2.         ///<summary>
  3.         /// The <see cref=“ListaPuestos” /> property’s name.
  4.         ///</summary>
  5.         publicconststring ListaPuestosPropertyName =“ListaPuestos”;
  6.         privateObservableCollection<PuestoModel> _listaPuestos;
  7.         publicObservableCollection<PuestoModel> ListaPuestos
  8.         {
  9.             get
  10.             {
  11.                 return _listaPuestos;
  12.             }
  13.             set
  14.             {
  15.                 if (_listaPuestos ==value) return;
  16.                 _listaPuestos =value;
  17.                 // Update bindings, no broadcast
  18.                 RaisePropertyChanged(ListaPuestosPropertyName);
  19.             }
  20.         }
  21.         #endregion

Con estas tres propiedades concluimos esta parte, continuaremos con la parte que nos permitirá desde la interfaz de usuario (Vista) decirle a nuestro ViewModel que ejecute acciones como Guardar, Eliminar, etc.

Esto se realiza a través de comandos, específicamente a través de la implementación de la Interfaz ICommand, gracias a MVVM Light Toolkit no tenemos que escribir toda la implementación, ya que el Toolkit nos provee de la clase RelayCommand que implementa la interfaz ICommand, esta clase permite definir a través de delegados un método que se llamará cuando se invoque el comando y un método que determinará si el comando se puede ejecutar.

Tenemos que agregar el siguiente namespace using GalaSoft.MvvmLight.Command

Lo siguiente que haremos es crear una nueva región, independiente de la region de las propiedades que se llame #region ViewModel Commands y aquí digitaremos los RelayCommand necesarios tal como sigue:

  1. #region ViewModel Commands
  2.         publicRelayCommand NewCommand { get; set; }
  3.         publicRelayCommand SaveCommand { get; set; }
  4.         publicRelayCommand DeleteCommand { get; set; }
  5.         publicRelayCommand<PuestoModel> SelectionChangedCommand { get; set; }
  6.         #endregion

 

Al primero le he puesto NewCommand, se puede utilizar el nombre que se desee, por ejemplo ComandoLimpiar, etc. public RelayCommand NewCommand {get; set;} es la declaración de un comando que nos permitirá limpiar propiedades (a su valor por omisión) y de forma automática, al estar estas enlazadas (binding) a la vista, limpiar la interfaz de usuario. Este comando se enlazará con un botón en la vista que se encargue de invocarlo.

public RelayCommand SaveCommand {get; set;} es la declaración de un comando que nos permitirá ejecutar la acción de enviar a guardar un nuevo puesto en la base de datos, estará enlazado en la vista por medio de un botón que se encargará de invocarlo

public RelayCommand DeleteCommand {get; set;} es la declaración de un comando que nos permitirá ejecutar la acción de eliminar un puesto de la base de datos

Y por último public RelayCommand<PuestoModel> SelectionChangedCommand {get; set;} es la declaración de un comando que en este caso recibirá por parámetro desde la vista, un objeto de tipo PuestoModel y nos permitirá saber cual es el puesto actualmente seleccionado, por ejemplo desde un DataGrid.

Lo que sigue es la implementación de esos comandos, creamos una region completamente aparte que se llame #region ViewModel Private Methods y adentro escribimos un método que nos permitirá registrar la implementación de los comandos como sigue a continuación:

  1. privatevoid RegisterCommands()
  2.         {
  3.             NewCommand              =newRelayCommand(New);
  4.             SaveCommand             =newRelayCommand(Save, CanSave);
  5.             DeleteCommand           =newRelayCommand(Delete, CanDelete);
  6.             SelectionChangedCommand =newRelayCommand<PuestoModel>(puesto =>
  7.             {
  8.                 if (puesto ==null) return;
  9.                 CurrentPuesto = puesto;
  10.                 Descripcion   = puesto.Descripcion;
  11.             });
  12.         }

Como se puede apreciar nos hace falta la implementación de los métodos New, Save, CanSave, Delete, CanDelete . Lo que haremos a continuación es escribir esos métodos para completar así el registro de los comandos. Creamos una nueva región que llamaremos #region ViewModel Public Methods, ahí deberá estar el constructor de la clase y los métodos anteriormente mencionados que nos permitirán interactuar con la clase Model y ésta a su vez con la base de datos a través de Entity Framework.

  1. #region ViewModel Public Methods
  2.         public PuestoViewModel()
  3.         {
  4.         }
  5.         publicvoid New()
  6.         {
  7.             Descripcion =string.Empty;
  8.             CurrentPuesto =null;
  9.         }
  10.         publicvoid Save()
  11.         {
  12.             if (CurrentPuesto ==null)
  13.             {
  14.                 var puesto =newPuestoModel { Descripcion = Descripcion };
  15.                 puesto.IdPuesto =PuestoModel.InsertPuesto(puesto.Descripcion);
  16.                 ListaPuestos.Add(puesto);
  17.             }
  18.             else
  19.             {
  20.                 CurrentPuesto.Descripcion = Descripcion;
  21.                 PuestoModel.UpdatePuesto(CurrentPuesto);
  22.             }
  23.             New();
  24.         }
  25.         publicbool CanSave()
  26.         {
  27.             return!string.IsNullOrEmpty(Descripcion);
  28.         }
  29.         publicvoid Delete()
  30.         {
  31.             PuestoModel.DeletePuesto(CurrentPuesto.IdPuesto);
  32.             ListaPuestos.Remove(CurrentPuesto);
  33.             New();
  34.         }
  35.         publicbool CanDelete()
  36.         {
  37.             return CurrentPuesto !=null;
  38.         }
  39.         #endregion

Como se puede observar el método New se encargará de limpiar las propiedades que van a interactuar con nuestra vista.

El método Save evalúa si CurrentPuesto es igual a un valor nulo en cuyo caso crea un objeto de tipo PuestoModel e inicializa la propiedad descripción del objeto con la propiedad Descripcion de nuestro ViewModel, luego ejecuta el método estático InsertPuesto y pasa por parámetro la descripción del puesto que queremos insertar y que a su vez retorna el Id entero auto incremental del código de puesto, para finalizar agregando el puesto a la colección de puestos tipo ObservableCollecion ListaPuestos que refrescará automáticamente nuestra Vista, en este caso un Grid con los puestos, si por el contrario CurrentPuesto no es nulo significa que se está en modo de edición de un puesto por consiguiente lo que procede es actualizar la propiedad descripcion del CurrentPuesto con la propiedad Descripción de nuestro ViewModel asumiendo que el usuario la ha modificado en el View, ejecutamos el método PuestoModel.UpdatePuesto pasando por parámetro el objeto PuestoModel que modificamos y finalizamos llamando al método New, para que limpie propiedades y a su vez la Vista.

El método CanSave será el encargado de activar o desactivar el botón “Guardar” en la vista, ya que este retorna un valor booleano dependiendo de si la propiedad Descripción está o no vacía.

Continuamos inspeccionando el método Delete que lo que hace es llamar al método estático DeletePuesto de la clase PuestoModel pasándole por parámetro el Id del puesto, luego elimina ese puesto de la lista de puestos de tipo ObservableCollection y ejecuta el método New.

El método CanDelete activará o desactivará el botón eliminar en la vista dependiendo de si la propiedad CurrentPuesto es null o no.

Una vez implementados los métodos de nuestros RelayCommand, continuamos con el constructor y lo que queremos que se realice cuando la vista “View” se ejecute por primera vez, y esto es, cargar la lista de puestos existentes en la base de datos en nuestra propiedad de tipo ObservableCollection ListaPuestos, además de inicializar nuestros RelayCommands ejecutando el método RegisterCommands.

  1. public PuestoViewModel()
  2.         {
  3.             ListaPuestos =newObservableCollection<PuestoModel>(PuestoModel.GetAllPuestos());
  4.             RegisterCommands();
  5.         }

 

Con esto finalizo el ViewModel de Puesto, lo que sigue es la Vista “View” que veremos en el paso 5 de la serie. Gracias!! Si desea conocer más acerca del autor de estos artículos puede acceder a su blog personal en la siguiente dirección http://zitrodan.wordpress.com/

MVVM Light Toolkit desde cero (paso 3)

August 2nd, 2011 No comments

En este tercer artículo de la serie acerca del patrón arquitectural Model – View – ViewModel voy a profundizar en la implementación del patrón utilizando MVVM Light Toolkit, en el anterior artículo MVVM Light Toolkit desde cero (paso 2) creamos la base de datos, el modelo utilizando ADO .NET Entity Framework y el proyecto WPF.

En el primer artículo MVVM Light Toolkit desde cero (paso 1) se explicó como realizar la instalación del Toolkit.

Existen varias formas de matar las pulgas y no hay recetas escritas en piedra que definan la forma en que se debe trabajar, cada implementación podría tener sus particularidades que ameriten modificaciones a lo que aquí expongo. Por ejemplo, se puede trabajar directamente con las entidades de negocio, en nuestro caso (Empleado y Puesto) accediendo directamente al modelo (Entity Framework) desde el ViewModel ó crear nuestras propias clases POCO (Plain Old CLR Object) y personalizar el desarrollo.

He visto ejemplos donde se accede directamente desde el ViewModel a los objetos del modelo (Entity Framework) viendo la capa, en nuestro caso Empleados.Data como la parte “Model” del Model – View – ViewModel. Lo que sucede en estos casos son varios inconvenientes, desde mi punto de vista no hay una adecuada separación de responsabilidades ya que la responsabilidad principal del ViewModel es interactuar con la Vista (View) enviando y recibiendo información, además, no se estaría encapsulando el código de acceso a datos ya que la teoría dice que un ViewModel debe corresponder a un View y si queremos reutilizar por ejemplo el código que accede a una lista de empleados en otro lugar de nuestro programa deberemos escribir nuevamente el código que nos retorne esa información.

A mi me ha dado buen resultado crear clases para cada entidad de negocio e implementar la interface INotifyPropertyChanged en cada una, así personalizo mejor el desarrollo y a la vez encapsulo el acceso a datos para que sea accedido por cualquier ViewModel que lo necesite, de esta forma estas clases en conjunto con Entity Framework pasarían a ser el componente “Model” de nuestra arquitectura.

Con ese prólogo paso entonces a la creación de las clases que nos permitirán acceder a los objetos del modelo utilizando LINQ y ADO.NET Entity Framework.

Lo primero es crear una clase base y abstracta que nos ayude en la implementación de la interfaz INotifyPropertyChanged hacia todas las clases de lógica de negocio. El enlace de datos o DataBinding es un componente básico del modelo MVVM y como centro del enlace de datos está la interfaz INotifyPropertyChanged, esta interfaz aparentemente simple se utiliza para sincronizar los cambios de propiedad de un objeto con la capa de interfaz de usuario (View).

La interfaz expone un único evento PropertyChanged. Además de especificar que una propiedad individual ha cambiado, el evento también puede indicar que todas las propiedades del objeto han cambiado utilizando una referencia nula o string.empty como el nombre de la propiedad en el PropertyChangedEventArgs.

Ubicados en el proyecto Empleados.WPF y en la carpeta Model hacemos clic derecho y Add Class, a esta clase la llamaremos BaseInpc.cs, agregamos el namespace System.ComponentModel y modificamos para que nuestra clase sea pública y abstracta ya que no queremos que se instancien objetos de esta clase. Seguidamente al nombre le la clase y con dos puntos “:” le decimos que nuestra clase va a implementar la interfaz INotifyPropertyChanged y con clic derecho accedemos al menú contextual y a la opción Implement Interface

BaseInpc_1

Esta acción lo que hará será crear el evento PropertyChanged, vamos a encapsular nuestro código en una región a la que llamaremos #region INotifyPropertyChanged Implementation
a continuación escribiremos el método que nos permitirá pasar por parámetro el nombre de la propiedad para que la interfaz haga su magia

  1. protectedvirtualvoid OnPropertyChanged(string propertyName)
  2.         {
  3.             var handler = PropertyChanged;
  4.             if (handler !=null)
  5.             {
  6.                 handler(this, newPropertyChangedEventArgs(propertyName));
  7.             }
  8.         }

Al final nuestra clase deberá verse de la siguiente forma:

  1. using System.ComponentModel;
  2. namespace Empleados.WPF.Model
  3. {
  4.     publicabstractclassBaseInpc : INotifyPropertyChanged
  5.     {
  6.         #region INotifyPropertyChanged Implementation
  7.         publiceventPropertyChangedEventHandler PropertyChanged;
  8.         protectedvirtualvoid OnPropertyChanged(string propertyName)
  9.         {
  10.             var handler = PropertyChanged;
  11.             if (handler !=null)
  12.             {
  13.                 handler(this, newPropertyChangedEventArgs(propertyName));
  14.             }
  15.         }
  16.         #endregion
  17.     }
  18. }

Lo siguiente es crear nuestras clases de lógica de negocio que encapsularan el acceso a datos, nuevamente ubicados en el proyecto Empleados.WPF y en la carpeta Model hacemos clic derecho y Add Class, la clase la llamaremos PuestoModel.cs ya que será la clase que se encargará de interactuar con objetos de tipo Puesto en nuestro modelo de ADO.NET Entity Framework. Incluimos en la recién creada clase el modificador de acceso “public” , heredamos de BaseInpc, agregamos el namespace Empleados.Data y en una región que llamaremos Model Attributes agregamos la variable que nos permitirá acceder a los objetos de nuestro modelo EmpleadosEntities de ADO.NET Entity Framework la cual llamaremos _context de tipo static. También agregamos un atributo para la descripción del puesto que será de tipo string

  1. using Empleados.Data;
  2. namespace Empleados.WPF.Model
  3. {
  4.     publicclassPuestoModel : BaseInpc
  5.     {
  6.         #region Model Attributes
  7.         privatestaticEmpleadosEntities _context;
  8.         privatestring _descripcion;
  9.         #endregion
  10.     }
  11. }

A continuación crearemos en una nueva región a la que llamaremos #region Model Properties las propiedades de nuestra clase, IdPuesto y Descripcion. Solamente a la propiedad Descripción le implementaremos el método OnPropertyChanged de nuestra clase BaseInpc ya que solamente queremos notificar cambios en esta propiedad.

  1. #region Model Properties
  2.         publicint IdPuesto { get; set; }
  3.         publicstring Descripcion
  4.         {
  5.             get { return _descripcion; }
  6.             set
  7.             {
  8.                 if (_descripcion ==value) return;
  9.                 _descripcion =value;
  10.                 OnPropertyChanged(“Descripcion”);
  11.             }
  12.         }
  13.         #endregion

Ahora vamos con los métodos de nuestra clase, creamos una nueva #region Public Model Methods en donde incluiremos todos los métodos públicos que expondrá nuestra clase.

El primero será el método que permita insertar en la base de datos un nuevo puesto, nuestro código deberá verse de la siguiente forma:

  1. publicstaticint InsertPuesto(string descripcion)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var puesto =newPuesto
  6.                                  {
  7.                                      descripcion = descripcion
  8.                                  };
  9.                 _context.AddToPuestos(puesto);
  10.                 _context.SaveChanges();
  11.                 return puesto.IdPuesto;
  12.             }
  13.         }

Aquí pasamos por parámetro (desde el ViewModel) un string con la descripción del puesto e instanciamos nuestro _context dentro de un using con la finalidad de que al cerrarlo se cierre también la conexión con nuestro modelo de datos. Instanciamos e inicializamos con valores un objeto de tipo Puesto y seguidamente utilizamos el método AddToPuestos para que se agregue a la colección de puestos de nuestro modelo y con el método SaveChanges insertamos en la base de datos, para terminar retornando el IdPuesto recién insertado.

Es importante destacar que aquí lo que perseguimos es que nuestros ViewModels no conozcan absolutamente nada acerca de como se interactúa con la base de datos, ni que tipo de base de datos es ó que ORM (Object Relational Mapper) se utiliza, de ahí el porqué, utilizamos la clase PuestoModel para que nuestros ViewModels no tengan que interactuar con objetos de nuestro modelo en ADO.NET Entity Framework.

A continuación el método que nos permitirá modificar la información de un puesto.

  1. publicstaticvoid UpdatePuesto(PuestoModel puestoModel)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var puesto = _context.Puestos.FirstOrDefault(p => p.IdPuesto == puestoModel.IdPuesto);
  6.                 if (puesto !=null) puesto.descripcion = puestoModel.Descripcion;
  7.                 _context.SaveChanges();
  8.             }
  9.         }

El siguiente método será el que nos permita eliminar un puesto de la base de datos, pasaremos por parámetro el idPuesto, a continuación el código:

  1. publicstaticvoid DeletePuesto(int idPuesto)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var puesto = _context.Puestos.FirstOrDefault(p => p.IdPuesto == idPuesto);
  6.                 _context.DeleteObject(puesto);
  7.                 _context.SaveChanges();
  8.             }
  9.         }

accedemos al puesto utilizando el método FirstOrDefault y una expresión lambda para la comparación de llaves, luego el método DeleteObject y SaveChanges para dar persistencia al cambio en este caso el borrado de información.

El último método que vamos a crear será aquel que nos retorne todos los puestos en la base de datos

  1. publicstaticList<PuestoModel> GetAllPuestos()
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 return _context.Puestos.Select(puesto =>newPuestoModel
  6.                                                     {
  7.                                                         IdPuesto = puesto.IdPuesto,
  8.                                                         Descripcion = puesto.descripcion
  9.                                                     }).ToList();
  10.             }
  11.         }

Aquí retornamos una lista de objetos de tipo PuestoModel, el mismo procedimiento haremos con la entidad Empleado, creando una clase EmpleadoModel que nos permita una correcta asignación de responsabilidades en este caso acceder al modelo ADO.NET Entity Framework utilizando LINQ para las operaciones hacia la base de datos. Pasemos entonces a la creación de de la clase para así ir terminando nuestro “Model” de la arquitectura Model – View – ViewModel.

Ubicados siempre en el proyecto Empleados.WPF y en la carpeta Model, damos clic derecho y Add Class, llamamos a la clase EmpleadoModel.cs le decimos que va a ser public y que heredamos de BaseInpc, creamos una #region Model Attributes e incluimos el atributo public static EmpleadosEntities _context y los demás atributos de la entidad Empleado como se ve en la imagen.

  1. using Empleados.Data;
  2. namespace Empleados.WPF.Model
  3. {
  4.     publicclassEmpleadoModel : BaseInpc
  5.     {
  6.         #region Model Attributes
  7.         privatestaticEmpleadosEntities _context;
  8.         privatestring _identificacion;
  9.         privatestring _nombre;
  10.         privatestring _primerApellido;
  11.         privatestring _segundoApellido;
  12.         privatestring _genero;
  13.         #endregion
  14.     }
  15. }

Seguimos con las propiedades de la clase

  1. #region Model Properties
  2.         publicint IdEmpleado { get; set; }
  3.         publicstring Identificacion
  4.         {
  5.             get { return _identificacion; }
  6.             set
  7.             {
  8.                 if(_identificacion ==value) return;
  9.                 _identificacion =value;
  10.                 OnPropertyChanged(“Identificacion”);
  11.             }
  12.         }
  13.         publicstring Nombre
  14.         {
  15.             get { return _nombre; }
  16.             set
  17.             {
  18.                 if (_nombre ==value) return;
  19.                 _nombre =value;
  20.                 OnPropertyChanged(“Nombre”);
  21.             }
  22.         }
  23.         publicstring PrimerApellido
  24.         {
  25.             get { return _primerApellido; }
  26.             set
  27.             {
  28.                 if (_primerApellido ==value) return;
  29.                 _primerApellido =value;
  30.                 OnPropertyChanged(“PrimerApellido”);
  31.             }
  32.         }
  33.         publicstring SegundoApellido
  34.         {
  35.             get { return _segundoApellido; }
  36.             set
  37.             {
  38.                 if (_segundoApellido ==value) return;
  39.                 _segundoApellido =value;
  40.                 OnPropertyChanged(“SegundoApellido”);
  41.             }
  42.         }
  43.         publicstring Genero
  44.         {
  45.             get { return _genero; }
  46.             set
  47.             {
  48.                 if (_genero ==value) return;
  49.                 _genero =value;
  50.                 OnPropertyChanged(“Genero”);
  51.             }
  52.         }
  53.         publicstring NombreCompleto
  54.         {
  55.             get { returnstring.Format(“{0} {1} {2}”, Nombre, PrimerApellido, SegundoApellido); }
  56.         }
  57.         publicPuestoModel Puesto { get; set; }

Una vez concluidas las propiedades pasamos a escribir los métodos para lo cual creamos una #region Public Model Methods e incluimos el método que nos permita Insertar en la base de datos un nuevo empleado

  1. publicstaticint InsertEmpleado(EmpleadoModel empleadoModel)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var empleado =newEmpleado
  6.                                    {
  7.                                        identificacion  = empleadoModel.Identificacion,
  8.                                        nombre          = empleadoModel.Nombre,
  9.                                        primerApellido  = empleadoModel.PrimerApellido,
  10.                                        segundoApellido = empleadoModel.SegundoApellido,
  11.                                        genero          = empleadoModel.Genero,
  12.                                        IdPuesto        = empleadoModel.Puesto.IdPuesto
  13.                                    };
  14.                 _context.AddToEmpleados(empleado);
  15.                 _context.SaveChanges();
  16.                 return empleado.IdEmpleado;
  17.             }
  18.         }

Continuamos con el método Update de un empleado.

  1. publicstaticvoid UpdateEmpleado(EmpleadoModel empleadoModel)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var empleado = (from e in _context.Empleados
  6.                                 where e.IdEmpleado == empleadoModel.IdEmpleado
  7.                                 select e).First();
  8.                 empleado.identificacion  = empleadoModel.Identificacion;
  9.                 empleado.nombre          = empleadoModel.Nombre;
  10.                 empleado.primerApellido  = empleadoModel.PrimerApellido;
  11.                 empleado.segundoApellido = empleadoModel.SegundoApellido;
  12.                 empleado.genero          = empleadoModel.Genero;
  13.                 empleado.IdPuesto        = empleadoModel.Puesto.IdPuesto;
  14.                 _context.SaveChanges();
  15.             }
  16.         }

En este caso he realizado una modificación en la forma de acceder al registro del empleado que queremos modificar, estoy utilizando LINQ to Entities en lugar de una expresión lambda, para que se observe también las distintas formas de trabajar con el acceso de datos en ADO.NET Entity Framework.

Seguimos con el método para eliminar un empleado

  1. publicstaticvoid DeleteEmpleado(int idEmpleado)
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 var empleado = (from e in _context.Empleados
  6.                                 where e.IdEmpleado == idEmpleado
  7.                                 select e).First();
  8.                 _context.DeleteObject(empleado);
  9.                 _context.SaveChanges();
  10.             }
  11.         }

y por último el método que retorna todos los empleados.

  1. publicstaticList<EmpleadoModel> GetAllEmpleados()
  2.         {
  3.             using (_context =newEmpleadosEntities())
  4.             {
  5.                 return _context.Empleados.Select(empleado =>
  6.                     newEmpleadoModel
  7.                         {
  8.                             IdEmpleado      = empleado.IdEmpleado,
  9.                             Identificacion  = empleado.identificacion,
  10.                             Nombre          = empleado.nombre,
  11.                             PrimerApellido  = empleado.primerApellido,
  12.                             SegundoApellido = empleado.segundoApellido,
  13.                             Genero          = empleado.genero,
  14.                             Puesto          =newPuestoModel
  15.                             {
  16.                                 IdPuesto    = empleado.Puesto.IdPuesto,
  17.                                 Descripcion = empleado.Puesto.descripcion
  18.                             }
  19.                         }).ToList();
  20.             }
  21.         }

Con esto doy por concluido el tercer artículo de la serie y cubierto el tema acerca de la parte “Model” de nuestra arquitectura Model – View – ViewModel . Podríamos escribir los test necesarios para probar nuestros métodos y en un ambiente de desarrollo normal es lo correcto, pero se sale un poco del alcance del artículo, ya que mi objetivo es mostrar el uso del patrón como tal y específicamente el MVVM Light Toolkit. Muy probablemente estaré incluyendo esos test en la versión final del código fuente. En el siguiente artículo estaré dando cobertura al ViewModel. Si desea conocer más acerca del autor de estos artículos puede acceder a su blog personal en la siguiente dirección http://zitrodan.wordpress.com/

MVVM Light Toolkit desde cero (paso 2)

August 2nd, 2011 1 comment

Este es el segundo artículo de una serie en la que estaré explicando como implementar el patrón Model – View – ViewModel. En el primer artículo se explicó como realizar la instalación de MVVM Light Toolkit.

Este segundo artículo tratará acerca de como utilizar el patrón en una arquitectura con ADO.NET Entity Framework comenzando por la creación de la base de datos, su implementación en un proyecto Visual Studio .NET 2010 y el esqueleto de arquitectura de nuestro proyecto de ejemplo.

Para este caso estoy utilizando SQL Server 2008 R2 y lo que voy a crear es una base de datos de empleados, así que comencemos por acceder a SQL Server Management Studio y creamos una nueva base de datos con el nombre Empleados, luego creamos una nueva tabla con las siguientes columnas:

Puesto

Esta tabla será la encargada de almacenar la información de puestos de trabajo, Indicamos que la llave primaria será el IdPuesto y que será un campo de tipo entero auto incremental, guardamos la tabla con el nombre Puesto.

Seguidamente creamos una nueva tabla con las siguientes columnas:

Empleado

Esta tabla será la encargada de almacenar la información relativa a empleados, de igual forma indicamos que la llave primaria será IdEmpleado y que será un campo de tipo entero auto incremental, guardamos la tabla con el nombre Empleado.

Establecemos la relación entre la tabla Puesto y la Tabla Empleado de la siguiente forma, ubicados en la tabla Empleado presionamos el botón “Relationships”, eso nos permite acceder al cuadro de diálogo para establecer la relación.

Relacion1

Relacion2

Cerramos el cuadro de diálogo y guardamos. No voy a ahondar mucho en el tema de la base de datos y algunos otros controles que deberíamos implementar para garantizar la consistencia de la información, como por ejemplo crear índices de tipo “Unique” para el campo de descripción del Puesto, igualmente para algunos otros campos de la tabla Empleado, ya que el objetivo del artículo es concentrarnos en la implementación del patrón arquitectural Model – View – View Model

Con estas dos tablas ya podemos comenzar a crear nuestro proyecto de ejemplo utilizando ADO.NET Entity Framework.

Accedemos a Visual Studio 2010 y creamos un nuevo proyecto de tipo Librería de Clases, al proyecto le daremos el nombre Empleados.Data y nuestro Solution se llamará MVVMEjemplo como se ve en la siguiente imagen.

NewProject

Eliminamos la clase que se crea por omisión y ubicados en el Solution Explorer y en nuestro proyecto Empleados.Data damos clic derecho para agregar un nuevo ítem de tipo ADO.NET Entity Data Model al que llamaremos EmpleadosModel.edmx y presionamos Add para crear nuestro modelo.

CreateModel

En el siguiente cuadro de diálogo seleccionamos generar nuestro modelo a partir de una base de datos y luego Next, en el siguiente cuadro de dialogo seleccionamos New Connection y establecemos la conexión con la base de datos Empleados.

NewConnection

DataConnection

Presionamos Next y en el siguiente cuadro de diálogo nos aseguramos de que las opciones de Pluralizar o Singularizar los nombres de los objetos generados esté marcado y la opción de incluir columnas de llaves foráneas en el modelo también, así como las tablas a partir de las cuales queremos generar nuestro modelo. Dejamos el nombre por omisión del Model Namespace como EmpleadosModel y luego presionamos Finish.

DataObjects

Model

Listo, hemos creado el modelo a partir de la base de datos, vamos a realizar algunas modificaciones a los nombres de objetos que Entity Framework a inferido utilizando la pluralización, el primero será a la propiedad de navegación en la tabla Puesto que por omisión tiene el nombre Empleadoes y no queremos que se llame así, la modificamos en la ventana de propiedades a Empleados.

Navigation

Luego seleccionamos la tabla Puesto en el modelo y en la ventana de propiedades modificamos el Entity Set Name, lo cambiamos a Puestos

Puestos

Igual hacemos con la tabla Empleado, la seleccionamos en el modelo y en la ventana de propiedades modificamos el Entity Set Name a Empleados

Empleados

Ahora vamos a crear nuestro proyecto de Windows Presentation Foundation que será la base de nuestra implementación del patrón arquitectural.

Ubicados en el Solution Explorer y en el Solution, damos clic derecho y seleccionamos Add New Project, el proyecto que vamos a crear será de tipo MvvmLight (WPF4) y lo llamaremos Empleados.WPF

NewWPFProject

Una vez creado el nuevo proyecto vamos a agregar las siguientes referencias que nos permitirán acceder a nuestro modelo, ubicados en References de nuestro proyecto Empleados.WPF damos clic derecho y Add Reference

La primer referencia será a System.Data.Entity

System.Data.Entity

La siguiente referencia será al proyecto Empleados.Data

Empleados.Data

Lo siguiente que haremos será copiar el App.Config de nuestro proyecto Empleados.Data y lo pegamos en el proyecto Empleados.WPF ya que este proyecto necesitará conocer la cadena de conexión para acceder a la base de datos, luego colocamos este proyecto como el proyecto de inicio.

StartUpProject

Ejecutamos el Proyecto presionando F5.

Main

Deberemos ver la siguiente pantalla indicándonos que todo está funcionando correctamente.

Para conocer mas acerca de ADO.NET Entity Framework recomiendo leer el libro de Julia Lerman

Programming Entity Framework: Building Data Centric Apps with the ADO.NET Entity Framework

En el siguiente artículo MVVM Light Toolkit desde cero (paso 3) continuaremos la construcción de nuestra aplicación. Si desea conocer más acerca del autor de estos artículos puede acceder al blog personal en la siguiente dirección http://zitrodan.wordpress.com/

MVVM Light Toolkit desde cero (paso 1)

August 2nd, 2011 3 comments

En este artículo voy a comentar acerca de cómo implementar el patrón Model – View – View Model utilizando MVVM Light Toolkit. Iniciaremos con el proceso de instalación desde cero, utilizando Visual Studio 2010 y luego en los siguientes artículos iremos desarrollando una aplicación de ejemplo utilizando una arquitectura MVVM sobre la base de ADO.NET Entity Framework, LINQ to Entities y Windows Presentation Foundation.

Si bien nos encontraremos muchos artículos que hablan acerca del patrón y de MVVM Light Toolkit, son pocos los que brindan ejemplos detallados en una arquitectura de aplicaciones del tipo LOB (Line of Business) y el uso en conjunto con Entity Framework.

Lo primero es conocer de qué se trata el patrón arquitectural y como nos facilita la construcción de nuestras aplicaciones. MVVM es en realidad un patrón que se construye en WPF y Silverlight y la idea principal es la separación del diseño o capa de presentación de la lógica de negocio y los datos; la capa de presentación será lo que se conocerá como (View), la lógica de negocio será el (ViewModel) y la data será el (Model). Si desea profundizar en el patrón como tal y conocer sus orígenes le recomiendo los siguientes enlaces a artículos y videos:

http://maromasdigitales.net/2010/05/patron-mvvm-explicado/

http://channel9.msdn.com/Events/PDC/PDC10/CD50

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

MVVM Light Toolkit

Obtenemos primero que todo los archivos necesarios para iniciar el proceso de instalación desde el sitio de Codeplex http://mvvmlight.codeplex.com/ A la fecha en que este artículo está siendo escrito la versión de MVVM Light Toolkit es la versión 3 Service Pack 1, así que el archivo que será descargado al computador será GalaSoft.MvvmLight.V3SP1WithHotfix.zip, se descomprime el archivo en una carpeta, una vez realizado esto el resultado serán los siguientes archivos:

  • GalaSoft.MvvmLight.Binaries.V3.zip
  • GalaSoft.MvvmLight.Snippets.V3.zip
  • GalaSoft.MvvmLight.Templates.V3.Blend3.zip
  • GalaSoft.MvvmLight.Templates.V3.Blend4.zip
  • GalaSoft.MvvmLight.Templates.V3.VS08.zip
  • GalaSoft.MvvmLight.Templates.V3.VS10.zip
  • GalaSoft.MvvmLight.Templates.V3.VS10X.zip

    Los archivos incluidos sirven para varios propósitos, entre ellos la utilización con Microsoft Expression Blend y distintas versiones de Visual Studio. Como nota importante al descomprimir los archivos en Windows Vista o Windows 7 estos quedan marcados como “no seguros” por el sistema operativo, se debe eliminar este bloqueo antes de descomprimirlos.

  • Seleccione el archivo zip
  • Clic derecho sobre el archivo y seleccione propiedades en el menú contextual
  • En el cuadro de diálogo de propiedades en la pestaña General, clic en el botón Unblock

    Unblock

    Instalación de los binaries

    Seleccione el archivo zip GalaSoft.MvvmLight.Binaries.V3.zip , clic derecho y la opción Extraer Todo, cambie la ruta donde los archivos serán extraídos  y coloque C:\ y a continuación confirme que si desea combinar los archivos dentro de la carpeta Program Files, Los archivos deberán quedar en la siguiente carpeta:

    C:\Program Files\Laurent Bugnion (GalaSoft)\Mvvm Light Toolkit\Binaries

    Instalación de templates para Visual Studio 2010

    En Visual Studio revise la ubicación desde donde los templates son cargados: Tools/ Options /Projects and Solutions

    ProjectTemplates

    copie la ruta sin la carpeta ProjectTemplates, por ejemplo en mi caso sería :

    C:\Users\Dan\Documents\Visual Studio 2010\Templates\

    A continuación seleccionemos el archivo zip GalaSoft.MvvmLight.Templates.V3.VS10.zip , clic derecho y la opción Extraer Todo, en el cuadro de dialogo pegue la ruta copiada anteriormente y confirme la extracción.

    Instalación de Snippets para Visual Studio 2010

    En Visual Studio revise la ubicación desde donde los snippets son cargados: Tools/ Code Snippets Manager / My Code Snippets

    Snippets

    copie la ruta en “Location:”, por ejemplo en mi caso sería :

    C:\Users\Dan\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets

    A continuación seleccionemos el archivo zip GalaSoft.MvvmLight.Snippets.V3.zip , clic derecho y la opción Extraer Todo, en el cuadro de dialogo pegue la ruta copiada anteriormente y confirme la extracción.

    Verificando la instalación

    Inicie Visual Studio

    Seleccione File / New Project

    Se deben visualizar los templates de proyectos MVVM Light bajo Visual C#

    Cree una nueva aplicación de tipo MVVMLight (WPF4)

    Abra la carpeta References en el Solution Explorer

    Asegúrese de que los archivos Dll GalaSoft.MvvmLight.WPF4, GalaSoft.MvvmLight.Extras.WPF4 y System.Windows.Interactivity están correctamente referenciados (sin un símbolo de advertencia)

    Verifying

    Más acerca de MVVM Light Toolkit puede ser accedido desde el sitio web de Galasoft http://www.galasoft.ch/mvvm/ y leyendo el blog de su creador, Laurent Bugnion http://blog.galasoft.ch/

    En el siguiente artículo MVVM Light Toolkit desde cero (paso 2) comenzaremos la construcción de nuestra aplicación. Si desea conocer más acerca del autor de estos artículos puede acceder a mi blog personal en la siguiente dirección http://zitrodan.wordpress.com/