Continuando con la serie acerca de la implementación del patrón arquitectural Model-View-ViewModel y en específico utilizando la herramienta MVVM Light Toolkit, este artículo dará por concluida la serie, con la implementación del ViewModel para Empleados y su correspondiente View.
Algunos seguidores del blog han sugerido nuevos ejemplos con algunas variantes y con la finalidad de visualizar las diferentes aristas que puede tener la implementación del patrón en conjunto con ADO.NET Entity Framework, lo cual estaré haciendo con mucho gusto en siguientes artículos.
Procedemos entonces a crear el ViewModel para Empleado, ubicados en el proyecto Empleados.WPF y en la carpeta ViewModel, damos clic derecho para agregar un nuevo ítem.
podemos eliminar los comentarios que se crean por omisión, agreguemos los siguientes namespaces System.Collections.ObjectModel, Empleados.WPF.Model, System.Collections.Generic y continuamos con la creación de las propiedades necesarias que estarán enlazadas al View, creamos una #region ViewModel Properties y dentro de esta otra #region ViewModel Property : ListaEmpleados , utilizando el snippet mvvminpc creamos una propiedad de tipo ObservableCollection<EmpleadoModel> que se llame ListaEmpleados.
- #region ViewModel Property : ListaEmpleados
- /// <summary>
- /// The <see cref="ListaEmpleados" /> property's name.
- /// </summary>
- public const string ListaEmpleadosPropertyName = "ListaEmpleados";
- private ObservableCollection<EmpleadoModel> _listaEmpleados;
- public ObservableCollection<EmpleadoModel> ListaEmpleados
- {
- get
- {
- return _listaEmpleados;
- }
- set
- {
- if (_listaEmpleados == value) return;
- _listaEmpleados = value;
- // Update bindings, no broadcast
- RaisePropertyChanged(ListaEmpleadosPropertyName);
- }
- }
- #endregion
La siguiente propiedad a incluir es CurrentEmpleado, creamos una #region ViewModel Property : CurrentEmpleado y dentro de esta una propiedad de tipo EmpleadoModel
- #region ViewModel Property : CurrentEmpleado
- /// <summary>
- /// The <see cref="CurrentEmpleado" /> property's name.
- /// </summary>
- public const string CurrentEmpleadoPropertyName = "CurrentEmpleado";
- private EmpleadoModel _currentEmpleado;
- public EmpleadoModel CurrentEmpleado
- {
- get
- {
- return _currentEmpleado;
- }
- set
- {
- if (_currentEmpleado == value) return;
- _currentEmpleado = value;
- // Update bindings, no broadcast
- RaisePropertyChanged(CurrentEmpleadoPropertyName);
- }
- }
- #endregion
La siguiente propiedad nos permitirá desplegar en el View los puestos registrados en la base de datos y a su vez enlazar el puesto seleccionado a un empleado. Se crea otra #region ViewModel Property : ListaPuestos y se crea una propiedad de tipo List<PuestoModel> llamada ListaPuestos
- #region ViewModel Property : ListaPuestos
- /// <summary>
- /// The <see cref="ListaPuestos" /> property's name.
- /// </summary>
- public const string ListaPuestosPropertyName = "ListaPuestos";
- private List<PuestoModel> _listaPuestos;
- public List<PuestoModel> ListaPuestos
- {
- get
- {
- return _listaPuestos;
- }
- set
- {
- if (_listaPuestos == value) return;
- _listaPuestos = value;
- // Update bindings, no broadcast
- RaisePropertyChanged(ListaPuestosPropertyName);
- }
- }
- #endregion
Continuamos con los comandos, agregamos el siguiente namespace Galasoft.MvvmLight.Command y creamos una #region ViewModel Commands y dentro de esta los comandos necesarios para manejar los botones del View y la selección en un Grid.
- #region ViewModel Commands
- public RelayCommand NewCommand { get; set; }
- public RelayCommand SaveCommand { get; set; }
- public RelayCommand DeleteCommand { get; set; }
- public RelayCommand<EmpleadoModel> SelectionChangedCommand { get; set; }
- #endregion
Luego una nueva #region ViewModel Public Methods y dentro de esta incluimos el método constructor de la clase, en el constructor cargamos la lista de todos los empleados que haya en la base de datos en la propiedad de tipo ObservableCollection ListaEmpleados, cargamos todos los puestos así como la inicialización de los RelayCommand.
- /// <summary>
- /// Initializes a new instance of the EmpleadoViewModel class.
- /// </summary>
- public EmpleadoViewModel()
- {
- ListaEmpleados = new ObservableCollection<EmpleadoModel>(EmpleadoModel.GetAllEmpleados());
- ListaPuestos = new List<PuestoModel>(PuestoModel.GetAllPuestos());
- RegisterCommands();
- New();
- }
Lo que sigue es la creación de los métodos necesarios para que los comandos “RelayCommand” funcionen adecuadamente. Métodos New, Save, CanSave, Delete, CanDelete.
- public void New()
- {
- CurrentEmpleado = new EmpleadoModel();
- }
- public void Save()
- {
- if (CurrentEmpleado.IdEmpleado == 0)
- {
- CurrentEmpleado.IdEmpleado = EmpleadoModel.InsertEmpleado(CurrentEmpleado);
- ListaEmpleados.Add(CurrentEmpleado);
- }
- else
- {
- EmpleadoModel.UpdateEmpleado(CurrentEmpleado);
- }
- New();
- }
- public bool CanSave()
- {
- return !string.IsNullOrEmpty(CurrentEmpleado.Identificacion) &&
- !string.IsNullOrEmpty(CurrentEmpleado.Nombre) &&
- !string.IsNullOrEmpty(CurrentEmpleado.PrimerApellido) &&
- !string.IsNullOrEmpty(CurrentEmpleado.Genero) &&
- CurrentEmpleado.Puesto != null;
- }
- public void Delete()
- {
- EmpleadoModel.DeleteEmpleado(CurrentEmpleado.IdEmpleado);
- ListaEmpleados.Remove(CurrentEmpleado);
- New();
- }
- public bool CanDelete()
- {
- return CurrentEmpleado.IdEmpleado != 0;
- }
procedemos a la inicialización de los comandos “RelayCommand” previamente declarados, creamos una #region ViewModel Private Methods y dentro de esta el método RegisterCommands
- #region ViewModel Private Methods
- private void RegisterCommands()
- {
- NewCommand = new RelayCommand(New);
- SaveCommand = new RelayCommand(Save, CanSave);
- DeleteCommand = new RelayCommand(Delete, CanDelete);
- SelectionChangedCommand = new RelayCommand<EmpleadoModel>(empleado =>
- {
- if (empleado == null) return;
- CurrentEmpleado = empleado;
- });
- }
- #endregion
Con esto concluímos el ViewModel de Empleados y como se puede apreciar a diferencia del ViewModel de Puesto, no se crearon propiedades individuales para enlazar a cada uno de los campos de captura de datos en el View como si se hizo con la descripción del Puesto, si no, que se está utilizando el objeto de tipo EmpleadoModel en este caso CurrentEmpleado, que a su vez cada una de sus propiedades implementa la interfaz INotifyPropertyChanged, para realizar la labor de DataBinding entre el ViewModel y el View como se verá a continuación con la creación del View, pero antes asegurémonos que el View podrá acceder el ViewModel por medio del ViewModelLocator.
Accedemos a ViewModelLocator.cs y creamos una nueva #region Empleado ViewModel seguidamente de la region Puesto ViewModel. Dentro de esta región utilizamos el snippet mvvmlocatorproperty que provee el MVVM Light Toolkit y una vez implementado el locator para EmpleadoViewModel realizamos un procedimiento similar al anterior locator para PuestoViewModel con el método Cleanup(), eliminando el creado por omisión pero dejando el llamado a ClearEmpleadoViewModel() en el otro método Cleanup() que ya se tenía como se ve a continuación.
- #region Empleado ViewModel
- private static EmpleadoViewModel _empleadoViewModel;
- /// <summary>
- /// Gets the EmpleadoViewModel property.
- /// </summary>
- public static EmpleadoViewModel EmpleadoViewModelStatic
- {
- get
- {
- if (_empleadoViewModel == null)
- {
- CreateEmpleadoViewModel();
- }
- return _empleadoViewModel;
- }
- }
- /// <summary>
- /// Gets the EmpleadoViewModel property.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
- "CA1822:MarkMembersAsStatic",
- Justification = "This non-static member is needed for data binding purposes.")]
- public EmpleadoViewModel EmpleadoViewModel
- {
- get
- {
- return EmpleadoViewModelStatic;
- }
- }
- /// <summary>
- /// Provides a deterministic way to delete the EmpleadoViewModel property.
- /// </summary>
- public static void ClearEmpleadoViewModel()
- {
- _empleadoViewModel.Cleanup();
- _empleadoViewModel = null;
- }
- /// <summary>
- /// Provides a deterministic way to create the EmpleadoViewModel property.
- /// </summary>
- public static void CreateEmpleadoViewModel()
- {
- if (_empleadoViewModel == null)
- {
- _empleadoViewModel = new EmpleadoViewModel();
- }
- }
- #endregion
- /// <summary>
- /// Cleans up all the resources.
- /// </summary>
- ///
- public static void Cleanup()
- {
- ClearMain();
- ClearEmpleadoViewModel();
- //ClearPuestoViewModel();
- }
Nótese el comentario en //ClearPuestoViewModel() en la imagen anterior, esto se debe a que no vamos a ejecutar la pantalla PuestoView, que a su vez por medio del locator crea una instancia de PuestoViewModel, si no que lo haremos solamente para el View de Empleado.
En este último artículo de la serie, voy a introducir algunos conceptos de WPF, crear una interfaz de usuario un poco más agradable y así aprovechar el tutorial para explorar el tema de controles de usuario, por que no sería lógico tener que estar creando la misma botonera (botones de Nuevo, Guardar, Eliminar, etc.) para cada programa de mantenimiento que vayamos a crear.
Ubicados en el Proyecto Empleados.WPF damos clic derecho, Add/New/Folder, le asignamos el nombre images, y dentro de este folder colocamos las imágenes que tendrán nuestros botones http://bit.ly/mWJzY9 , una vez descargadas y ubicados en el folder recién creado, damos clic derecho Add/Existing Item… para seleccionar las imágenes
Crearemos algunos estilos para darle a nuestra interfaz de usuario un aspecto diferente y moderno, algunos de estos estilos serán generales para toda la aplicación, por lo cual estarán ubicados en el App.xaml y otros estilos serán locales para uso únicamente del View ó control donde se definan. Accedemos al archivo App.xaml y dentro de la etiqueta <Application.Resources> incluimos lo siguiente:
- Application.Resources>
- <!–Global View Model Locator–>
- <vm:ViewModelLocator x:Key="Locator"
- d:IsDataSource="True" />
- <LinearGradientBrush
- x:Key="BottomBorderBackground"
- EndPoint="0.5,1"
- StartPoint="0.5,0">
- <GradientStop Color="#FF96BFCD" Offset="0" />
- <GradientStop Color="#FF4A7681" Offset="1" />
- </LinearGradientBrush>
- <LinearGradientBrush
- x:Key="InnerBorderBackground"
- EndPoint="0.5,1"
- StartPoint="0.5,0">
- <GradientStop Color="#FFF3F3F3" Offset="0" />
- <GradientStop Color="#FFF3F3F3" Offset="1" />
- <GradientStop Color="#FFE0E0E0" Offset="0.45" />
- </LinearGradientBrush>
- </Application.Resources>
Vamos a crear el control de usuario que nos permitirá colocar los botones que tendrán nuestros programas de mantenimiento, ubicados en el proyecto Empleados.WPF damos clic derecho, Add/New/Folder, le asignamos el nombre controles y ubicados en este folder damos nuevamente clic derecho Add/User Control…, le asignamos el nombre BotonesControl.xaml , ajustamos los valores de d:Designheight=”50” y d:DesignWith=”600” en el código xaml y antes de la declaración de la etiqueta <Grid> que se crea por omisión incluimos la etiqueta <UserControl.Resources> dentro de esta etiqueta se incluirán algunos estilos de uso local, solamente para este control de usuario.
- <UserControl.Resources>
- <Style
- x:Key="myLabelStyle"
- TargetType="{x:Type Label}">
- <Setter Property="Foreground" Value="White" />
- <Setter Property="FontSize" Value="10" />
- <Setter Property="Margin" Value="0,-5,0,0" />
- </Style>
- <Style
- x:Key="myImageStyle"
- TargetType="{x:Type Image}">
- <Setter Property="Width" Value="26" />
- <Setter Property="Height" Value="26" />
- <Setter Property="Margin" Value="0,3,0,0" />
- </Style>
- <Style
- x:Key="myButtonStyle"
- TargetType="{x:Type Button}">
- <Setter Property="BorderBrush" Value="Transparent" />
- <Setter Property="Background" Value="Transparent"/>
- <Setter Property="Cursor" Value="Hand"/>
- </Style>
- <Style
- x:Key="myStackPanelStyle"
- TargetType="StackPanel">
- <Setter Property="Background" Value="Transparent"/>
- <Setter Property="Margin" Value="2,0" />
- </Style>
- </UserControl.Resources>
Luego a la etiqueta <Grid> le agregamos los siguientes valores
- <Grid
- VerticalAlignment="Top"
- HorizontalAlignment="Stretch"
- Height="50">
- <Grid.Background>
- <LinearGradientBrush
- EndPoint="0.5,1"
- StartPoint="0.5,0">
- <GradientStop Color="#FF999999" Offset="0" />
- <GradientStop Color="#FF142533" Offset="1" />
- <GradientStop Color="#FF3F3F3F" Offset="0.5" />
- <GradientStop Color="#FF0D161D" Offset="0.5" />
- </LinearGradientBrush>
- </Grid.Background>
- </Grid>
Siempre dentro de la etiqueta <Grid> y después de la declaración de </Grid.Background> vamos a crear los botones de nuestro control, pero antes debemos crear el contenedor donde estarán los botones, para eso creamos un <StackPanel Orientation=”Horizontal”> y dentro del StackPanel los botones:
- <Grid
- VerticalAlignment="Top"
- HorizontalAlignment="Stretch"
- Height="50">
- <Grid.Background>
- <LinearGradientBrush
- EndPoint="0.5,1"
- StartPoint="0.5,0">
- <GradientStop Color="#FF999999" Offset="0" />
- <GradientStop Color="#FF142533" Offset="1" />
- <GradientStop Color="#FF3F3F3F" Offset="0.5" />
- <GradientStop Color="#FF0D161D" Offset="0.5" />
- </LinearGradientBrush>
- </Grid.Background>
- <StackPanel Orientation="Horizontal">
- <Button
- Style="{StaticResource myButtonStyle}"
- Command="{Binding NewCommand, Mode=OneWay}">
- <StackPanel Style="{StaticResource myStackPanelStyle}">
- <Image Source="/images/New.png" Style="{StaticResource myImageStyle}" />
- <Label Content="Nuevo" Style="{StaticResource myLabelStyle}" />
- </StackPanel>
- </Button>
- <Button
- Style="{StaticResource myButtonStyle}"
- Command="{Binding SaveCommand, Mode=OneWay}">
- <StackPanel Style="{StaticResource myStackPanelStyle}">
- <Image Source="/images/Save.png" Style="{StaticResource myImageStyle}" />
- <Label Content="Grabar" Style="{StaticResource myLabelStyle}" />
- </StackPanel>
- </Button>
- <Button
- Style="{StaticResource myButtonStyle}"
- Command="{Binding DeleteCommand, Mode=OneWay}">
- <StackPanel Style="{StaticResource myStackPanelStyle}">
- <Image Source="/images/Delete.png" Style="{StaticResource myImageStyle}" />
- <Label Content="Borrar" Style="{StaticResource myLabelStyle}" />
- </StackPanel>
- </Button>
- <Button
- Style="{StaticResource myButtonStyle}"
- Command="{Binding SearchCommand, Mode=OneWay}">
- <StackPanel Style="{StaticResource myStackPanelStyle}">
- <Image Source="/images/Search.png" Style="{StaticResource myImageStyle}" />
- <Label Content="Buscar" Style="{StaticResource myLabelStyle}" />
- </StackPanel>
- </Button>
- <Button
- Style="{StaticResource myButtonStyle}"
- Command="{Binding RefreshCommand, Mode=OneWay}">
- <StackPanel Style="{StaticResource myStackPanelStyle}">
- <Image Source="/images/Refresh.png" Style="{StaticResource myImageStyle}" />
- <Label Content="Refrescar" Style="{StaticResource myLabelStyle}" />
- </StackPanel>
- </Button>
- </StackPanel>
- </Grid>
Como se puede apreciar, para cada botón hemos establecido la propiedad Command que se estará enlazando en el ViewModel con los RelayCommand creados anteriormente y hemos optimizado el código xaml con los estilos creados anteriormente en la sección <UserControl.Resources> a fin de reutilizarlos y no tener que escribir las mismas propiedades para cada uno de los botones. Al final nuestro control de usuario debería verse de la siguiente forma:
Compilamos el Proyecto, así nos aseguramos que todo vaya bien, y siempre ubicados siempre en el Proyecto Empleados.WPF y en la carpeta View, damos clic derecho y Add New Item para crear la Vista EmpleadosView.xaml
una vez creada la pantalla, en el código XAML ingresamos los valores de d:DesignWidth=”600” y d:DesignHeight=”640”, ingresamos la propiedad WindowsStartupLocation=”CenterScreen”, Title=”Gestión de Empleados” y DataContext=”{Binding EmpleadoViewModel, Source={StaticResource Locator}}” y el namespace xmlns:usrControl=”clr-namespace:Empleados.Wpf.controles”, luego agregamos al <Grid> la definición de 2 Rows y seguidamente al cierre de la definición de los Rows, agregamos el user Control de los botones colocando lo siguiente: <usrControl:BotonesControl Grid.Row=”0”> , Luego creamos un par de controles de tipo <Border>, uno dentro del otro, hasta ahora el código xaml debería verse así:
- <Window x:Class="Empleados.WPF.View.EmpleadoView"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d"
- d:DesignWidth="600"
- d:DesignHeight="640"
- WindowStartupLocation="CenterScreen"
- Width="600"
- Height="640"
- DataContext="{Binding EmpleadoViewModel, Source={StaticResource Locator}}"
- Title="Gesti?n de Empleados"
- xmlns:usrControl="clr-namespace:Empleados.WPF.controles">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="50" />
- <RowDefinition />
- </Grid.RowDefinitions>
- <usrControl:BotonesControl
- Grid.Row="0" />
- <Border
- Grid.Row="1"
- Background="{StaticResource BottomBorderBackground}">
- <Border
- Margin="10,8,10,10"
- CornerRadius="4"
- Background="{StaticResource InnerBorderBackground}">
- </Border>
- </Border>
- </Grid>
- </Window>
Dentro del último <Border> agregamos un <Grid> y dentro de este lo siguiente es colocar los controles necesarios para la captura de información del mantenimiento de empleados, agregamos los siguientes namespaces al código xaml xmlns:i=”http://schemas.microsoft.com/expression/2010/interactivity” y xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
- <Grid>
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,23,0,0"
- Text="Identificaci?n"
- VerticalAlignment="Top" />
- <TextBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,20,0,0"
- Text="{Binding Path=CurrentEmpleado.Identificacion, UpdateSourceTrigger=PropertyChanged}"
- VerticalAlignment="Top"
- Width="173" />
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,52,0,0"
- Text="Nombre"
- VerticalAlignment="Top" />
- <TextBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,49,0,0"
- Text="{Binding Path=CurrentEmpleado.Nombre, UpdateSourceTrigger=PropertyChanged}"
- VerticalAlignment="Top"
- Width="173" />
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,81,0,0"
- Text="Primer Apellido"
- VerticalAlignment="Top" />
- <TextBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,78,0,0"
- VerticalAlignment="Top"
- Width="173"
- Text="{Binding Path=CurrentEmpleado.PrimerApellido, UpdateSourceTrigger=PropertyChanged}" />
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,110,0,0"
- Text="Segundo Apellido"
- VerticalAlignment="Top" />
- <TextBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,107,0,0"
- Text="{Binding Path=CurrentEmpleado.SegundoApellido, UpdateSourceTrigger=PropertyChanged}"
- VerticalAlignment="Top"
- Width="173" />
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,139,0,0"
- Text="G?nero"
- VerticalAlignment="Top" />
- <ComboBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,136,0,0"
- VerticalAlignment="Top"
- Width="173"
- Text="{Binding Path=CurrentEmpleado.Genero, UpdateSourceTrigger=PropertyChanged}">
- <ComboBoxItem
- Content="Masculino" />
- <ComboBoxItem
- Content="Femenino" />
- </ComboBox>
- <TextBlock
- Height="23"
- HorizontalAlignment="Left"
- Margin="21,168,0,0"
- Text="Puesto"
- VerticalAlignment="Top" />
- <ComboBox
- Height="23"
- HorizontalAlignment="Left"
- Margin="122,168,0,0"
- VerticalAlignment="Top"
- Width="173"
- ItemsSource="{Binding Path=ListaPuestos}"
- SelectedItem="{Binding Path=CurrentEmpleado.Puesto, UpdateSourceTrigger=PropertyChanged}"
- Text="{Binding Path=CurrentEmpleado.Puesto.Descripcion, UpdateSourceTrigger=PropertyChanged}"
- DisplayMemberPath="Descripcion" />
- <DataGrid
- AutoGenerateColumns="False"
- Height="288"
- HorizontalAlignment="Left"
- Margin="11,217,0,0"
- Name="dataGrid1"
- VerticalAlignment="Top"
- Width="529"
- ItemsSource="{Binding Path=ListaEmpleados, UpdateSourceTrigger=PropertyChanged}"
- CanUserAddRows="False">
- <DataGrid.Columns>
- <DataGridTextColumn
- Binding="{Binding Path=Identificacion, UpdateSourceTrigger=PropertyChanged}"
- Header="Identificacion"
- Width="100"
- IsReadOnly="True" />
- <DataGridTextColumn
- Binding="{Binding Path=Nombre, UpdateSourceTrigger=PropertyChanged}"
- Header="Nombre"
- Width="125"
- IsReadOnly="True" />
- <DataGridTextColumn
- Binding="{Binding Path=PrimerApellido, UpdateSourceTrigger=PropertyChanged}"
- Header="Primer Apellido"
- Width="150"
- IsReadOnly="True" />
- <DataGridTextColumn
- Binding="{Binding Path=Genero, UpdateSourceTrigger=PropertyChanged}"
- Header="Genero"
- Width="130"
- IsReadOnly="True" />
- </DataGrid.Columns>
- <i:Interaction.Triggers>
- <i:EventTrigger
- EventName="SelectionChanged">
- <cmd:EventToCommand
- Command="{Binding SelectionChangedCommand, Mode=OneWay}"
- CommandParameter="{Binding SelectedItem, ElementName=dataGrid1}" />
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </DataGrid>
- </Grid>
Para finalizar y desplegar la aplicación modificamos el archivo App.xaml y la sección StartupUri=”View/EmpleadoView.xaml”, la aplicación deberá lucir así:
Tal y como lo mencioné en el artículo anterior, he obviado algunos procedimientos con la finalidad de no hacer el post mas grande de lo que ya es, concentrándome en las particularidades que hacen este mantenimiento diferente al anterior que habíamos desarrollado de Puestos.
No me queda mas que agradecer a los lectores que han seguido esta serie de artículos acerca de como implementar el patrón Model-View-ViewModel y en específico utilizando la herramienta MVVM Light Toolkit, ADO.NET Entity Framework y LINQ que eran los objetivos de la serie. Estaré complementado con otros artículos las sugerencias que han manifestado los seguidores del blog, así como también escribiendo acerca de otras funcionalidades que provee MVVM Light Toolkit, como la funcionalidad de “Messenger”, además de escribir algunos artículos trabajando directamente con Microsoft Expression Blend para el diseño de Interfaces ricas en UX en conjunto con MVVM Light Toolkit siempre en la línea de utilizar el patrón para el desarrollo de aplicaciones, así como aplicaciones para Windows Phone 7.
El código fuente de todo el desarrollo de la serie de artículos puede ser descargado aquí :
Saludos y nos vemos en el siguiente post.

1 comment
Yair Granados says:
May 8, 2012
Interesante aporte… Aprendí mucho, espero y colocaran la forma de hacerlo en silverlight… Muchas Gracias!!