9.27.2009

Entity Framework: Eliminando Entidades de una Lista y Refrescando el UI

En el post anterior vimos como implementar la interface IEquatable<T> para poder utilizar los métodos de la lista sobre las entidades tales como Contains e IndexOf. En este post vamos a ver como eliminar entidades de la lista y notificar este evento al UI que tenga binding con la lista afectada. Al mismo tiempo vamos a aplicar la modificación a la base de datos.

Eliminando una Entidad de la Lista y Notificando el UI

El primer paso para eliminar una entidad de la lista que tenemos ligada a nuestro UI es definir como vamos a llevar a cabo este procedimiento. En primera instancia vamos a agregar dos botones más a nuestra pantalla, uno para eliminar y otro para aplicar cambios. El diseño de la pantalla quedará como se observa a continuación

image

El siguiente paso es cambiar la forma en que hacemos binding de los datos desde el EF. Anteriormente utilizabamos una lista para almacenar nuestras entidades y así presentarlas en el UI, ahora vamos a cambiar esa lista por una colección del tipo ObservableCollection. Las colecciones de este tipo tienen la particularidad que notifica cuando se agrega o se elimina un elemento de la colección, o cuando se recarga la misma. Para esto, declaramos la colección del tipo de la entidad Empresa como lo hicimos en el post anterior.

ObservableCollection<Empresa> m_Empresas = new ObservableCollection<Empresa>();

public ObservableCollection<Empresa> Empresas
{
get { return m_Empresas; }
set { m_Empresas = value; }
}


El siguiente paso es hacer el binding desde el EF y ligarlo con el control a través del cual queremos desplegar los datos. En nuestro caso tenemos una función que nos devuelve la colección de empresas – ObtenerEmpresa – y en el load de la forma, procedemos a ligar la colección al Grid de Empresas.



private void Window_Loaded(object sender, RoutedEventArgs e)
{
Empresas = ObtenerEmpresas();
dgEmpresas.ItemsSource = Empresas;
}
public ObservableCollection<Empresa> ObtenerEmpresas()
{
UseCasesEntities entities = GetEntity();
var Empresas = from e in entities.Empresa select e;
return new ObservableCollection<Empresa>(Empresas.ToList());
}



El método GetEntity() es un método que utiliza un patrón singleton para obtener siempre el mismo contexto del Entity Framework y así poder eliminar, modificar, o agregar entidades al repositorio de datos.



static UseCasesEntities entities;

private static UseCasesEntities GetEntity()
{
if (entities == null)
entities = new UseCasesEntities();
return entities;
}



El siguiente paso es agregar el código necesario para poder eliminar la entidad de la colección cuando el usuario así lo requiere, es decir cuando seleccione una entidad y de clic en el botón de eliminar. En este caso obtenemos la entidad seleccionada casteando la fila seleccionada a un objeto tipo Empresa, seguidamente y gracias a la implementación de IEquatable<T> podemos utilizar el método remove de la colección para remover la entidad de la colección. También procedemos a marcar el objeto seleccionado como eliminado dentro del contexto del entity framework.



private void btnEliminar_Click(object sender, RoutedEventArgs e)
{
Empresa tmpEmpresa = dgEmpresas.SelectedItem as Empresa;
Empresas.Remove(tmpEmpresa);
GetEntity().DeleteObject(tmpEmpresa);
}



Con estos cambios, ya tenemos la funcionalidad a nivel de UI, si ejecutamos el código anterior, vamos a eliminar los ítems de la lista, y sin refrescar la lista, obtenemos el cambio en el UI.



Aplicando los cambios en el UI



Una vez realizados los cambios en el UI, debemos persistir los cambios en la base de datos. Para llevar a cabo esta funcionalidad, simplemente agregamos el siguiente código al manejador del evento clic del botón aplicar.



private void btnAplicar_Click(object sender, RoutedEventArgs e)
{
GetEntity().SaveChanges();
}





En este caso, solamente ejecutamos el método SaveChanges para persistir el cambio o los cambios a la base de datos.



9.12.2009

Extendiendo el Entity Framework – Comparación y Búsqueda de Entidades

Una de las tareas más comunes cuando trabajamos con el Entity Framework es la búsqueda de las entidades en una lista y la comparación de las mismas. El EF nos provee la facilidad de agregar código para comparación a través de la Interface IEquatable y las clases parciales.

Interface IEquatable<T>

La interface IEquatable<T> de acuerdo al msdn se define como una interface que define un metodo de igualdad, el cual determina la igualdad de las instancias del tipo implementado. Por otro lado y para aclarar por adelantado, la Interface IComparable<T> define un metodo de comparación generalizado para ordenamiento de instancias.

IEquatable<T> se usa normalmente por colecciones genericas tales como List<T> y LinkedList<T> para ser utilizado en métodos tales como Contains, IndexOf, Remove, etc. Esta interface se debe de implementar en cualquier objeto que se va a almacenar en colecciones genéricas.

Extendiendo una Entidad con IEquatable<T>

El primer paso para extender una entidad del Entity Framework es crear una clase que contenga este código adicional. En este caso, vamos a extender la entidad Empresa y por lo tanto, vamos a crear una clase parcial que igualmente se va a llamar empresa. Para esto procedemos a agregar la clase en el proyecto donde definimos el modelo del Entity Framework.

imageSeguidamente procedemos a poner la clase recién creada como pública y parcial; esto va a permitir que esta clase se compile en conjunto con la clase generada por el EF en una sola clase,  por lo que toda la funcionalidad que agregemos a esta clase será parte de la clase Empresa del EF. Además, por estar en una clase parcial, si tenemos que regenerar el modelo, no vamos a perder la lógica incluída.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Samples
{
public partial class Empresa
{
}
}
Como podemos ver en la siguiente figura, la clase que genera el EF es también parcial y por lo tanto podemos agregar la funcionalidad que deseamos.


image Seguidamente procedemos a implementar la clase IEquatable<T> para poder definir como vamos a hacer las comparaciones en nuestra entidad. Nótese como el método definido en el contrato de la interface – Equals – recibe otra entidad de tipo empresa para llevar a cabo la comparación.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
//Aquí vamos a implementar nuestra comparación
return true;
}

#endregion
}



Para este caso especifico, quiero que la empresa se pueda comparar tanto por el campo Id como por el nombre, es decir, buscarla en la lista por nombre y buscarla por Id para cuando por ejemplo el item se selecciona desde un combo box.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
if (this.Id == other.Id || this.Nombre == other.Nombre)
return true;
return false;
}

#endregion
}



Como podemos ver, el método Equals contiene la definición de comparación que nosotros creamos conveniente para poder utilizar la entidad en nuestra lógica de negocios.



Ahora vamos a utilizar nuestra entidad para diferentes propósitos. Inicialmente vamos a tener una pantalla para buscar empresas por nombre tal y como luce a continuación.



image La idea es buscar entre las empresas del grid la que deseamos y desplegarla en un diálogo modal. Este dialogo que se presentará de forma modal es el siguiente:



imageEl siguiente paso es crear la lógica para presentar un detalle de una empresa en el dialogo anterior, lo cual hacemos con el siguiente código:



public partial class frmEmpresa : Window
{
private Empresa m_Empresa;

public Empresa EmpresaProp
{
get { return m_Empresa; }
set { m_Empresa = value; }
}

public frmEmpresa(Empresa pEmpresa)
{
InitializeComponent();
EmpresaProp = pEmpresa;
txtNombre.Text = EmpresaProp.Nombre;
txtDireccion.Text = EmpresaProp.Direccion;
txtTelefono.Text = EmpresaProp.Telefono;
txtEmail.Text = EmpresaProp.Email;
}

public frmEmpresa()
{
InitializeComponent();
}

private void btnCerrar_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}


Ahora vamos a programar el código necesario para buscar la entidad deseada en la lista que hemos cargado en el grid y si la encontramos, procedemos a invocar la forma anterior para presentar su detalle.



public partial class BuscarEmpresa : Window
{
List<Empresa> m_Empresas = new List<Empresa>();

public List<Empresa> Empresas
{
get { return m_Empresas; }
set { m_Empresas = value; }
}
public BuscarEmpresa()
{
InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
Empresas = ObtenerEmpresas();
dgEmpresas.ItemsSource = Empresas;

}

public List<Empresa> ObtenerEmpresas()
{
UseCasesEntities entities = new UseCasesEntities();
var Empresas = from e in entities.Empresa select e;
return Empresas.ToList();
}

private void btnBuscar_Click(object sender, RoutedEventArgs e)
{
Empresa empresaTmp = new Empresa();
empresaTmp.Nombre = txtEmpresa.Text;

if (Empresas.Contains(empresaTmp))
{

frmEmpresa frm = new frmEmpresa(Empresas[Empresas.IndexOf(empresaTmp)]);
frm.ShowDialog();
}
else
MessageBox.Show("Empresa no existe", "Mensaje");
}
}



El código que nos interesa es el código del evento click del botón buscar. Lo primero que hacemos es crear una instancia de la entidad empresa y proceder a asignarle el valor digitado por el usuario en el textbox. Seguidamente, vamos a pedirle a la lista de empresas ( declarada al inicio de la clase ) a través del método Contains, si tiene una entidad igual a la que le estoy enviando. Nótese que aunque no he cargado todos los campos, el llamado a Contains busca la implementación de la interface IEquatable<T> para hacer la búsqueda, por esta razón si digitamos el nombre de alguna empresa que exista, el método lo encuentra. Si el existe, el siguiente paso es desplegarlo en la pantalla de detalle pasándola por parámetro. Para lograr esta funcionalidad tenemos que ir a obtener la entidad de la lista, lo cual se logra con una combinación de un método de la lista – IndexOf - y el indexador de la misma []. IndexOf utiliza la comparación que nos provee la interface IEquatable<T>. El resultado al ejecutar el ejemplo anterior es el siguiente:



imageEn los post siguientes vamos a profundizar en este tema.













9.02.2009

SpellCheck en WPF

Una característica interesante que me encontré trabajando en el desarrollo de una aplicación WPF es la posibilidad de tener SpellCheck en la edición de texto en los controles TextBox y RichTextBox. Además, la forma de lograrlo es muy simple. Inicialmente se habilita la propiedad SpellCheck.IsEnabled="True" y se indica cual lenguaje se desea para hacer el spell check con la propiedad Language. La siguiente figura nos muestra como llevar a cabo esta configuración:

image Cuando ejecutamos la aplicación y escribimos palabras en español incorrectas, estas serán subrayadas con rojo y si le damos botón derecho sobre la palabra, un context menu nos hará sugerencias para reemplazar la palabra incorrecta.

image El diccionario que se utiliza para realizar este spellcheck en este momento soporta 4 lenguajes: inglés, español, francés y alemán. La lista de sugerencias son una copia del diccionario de Microsoft Office 2007 y al ser una copia, no se requiere tener instalado Office en la máquina.

Technorati Tags: ,,