.NET RIA Services práctico. Selección en ComboBox con carga de datos en DataGrid (y 3)

En esta tercera entrega, que concluye el presente artículo sobre .NET RIA Services, veremos cómo dotar de mayor funcionalidad al servicio de dominio, añadiéndole nuevos métodos con los que enriquecer la interacción entre las capas cliente y servidora de nuestra aplicación. También explicaremos el modo de rellenar con valores el control DataGrid, objetivo principal del ejemplo.

Ordenando la lista de valores mediante LINQ

Posiblemente nos hayamos percatado de que al desplegar la lista de valores del ComboBox, estos se muestran sin un orden preestablecido, cuando lo más adecuado sería que estuvieran ordenados alfabéticamente.

Aunque la solución más sencilla sería modificar la vista de la base de datos para que devolviera el conjunto de resultados ya ordenado, en esta ocasión vamos a optar por la vía difícil, es decir, realizar la ordenación desde el código de la aplicación. Disponemos de dos técnicas para lograrlo.

La primera de estas técnicas pasa por manipular el objeto EntityQuery que devuelve el método GetPaisesPedidosQuery del contexto de dominio, aplicándole la ordenación mediante la cláusula orderby de LINQ, obteniendo de esta manera un nuevo objeto EntityQuery, que pasaremos como parámetro al método NorthwindContext.Load.

public partial class MainPage : UserControl
{
    NorthwindContext oNorthwindContext = new NorthwindContext();

    public MainPage()
    {
        InitializeComponent();

        EntityQuery<PaisesPedido> qryConsulta = from oPaisPedido
                                                in oNorthwindContext.GetPaisesPedidosQuery()
                                                orderby oPaisPedido.ShipCountry
                                                select oPaisPedido;

        LoadOperation<PaisesPedido> oLoadOperation = oNorthwindContext.Load(qryConsulta);
        this.cboPaises.ItemsSource = oLoadOperation.Entities;
    }
    //....
}

La siguiente imagen muestra la lista de elementos del ComboBox ordenados gracias a esta técnica.

La segunda técnica consiste en crear un nuevo método en el servicio de dominio, que devuelva la lista de entidades, ordenada mediante el método OrderBy de LINQ.

[EnableClientAccess()]
public class NorthwindService : LinqToSqlDomainService<NorthwindDataContext>
{
    //....
    public IQueryable<PaisesPedido> GetPaisesPedidosOrdenados()
    {
        return this.Context.PaisesPedidos.OrderBy(oPaisPedido => oPaisPedido.ShipCountry);
    }
}

Volveremos a compilar la solución, de forma que .NET RIA Services genere el código correspondiente para la capa cliente de la aplicación, y desde el constructor de la página Silverlight invocaremos a este nuevo método.

//....
public MainPage()
{
    InitializeComponent();

    oNorthwindContext.Load(oNorthwindContext.GetPaisesPedidosOrdenadosQuery());
    this.cboPaises.ItemsSource = oNorthwindContext.PaisesPedidos;
}

Carga de registros en el DataGrid

El siguiente paso consistirá en cargar en el DataGrid aquellos registros de la tabla Orders, cuyo campo ShipCountry sea igual al valor seleccionado en el ComboBox. Actualmente, el servicio de dominio sólo dispone del método GetOrders para obtener los valores de esta tabla, por lo que tendremos que añadir un nuevo método, al que daremos el nombre GetOrdersCiudadEntrega, que recibirá como parámetro una cadena con el nombre de la ciudad, que actuará como filtro en la devolución de los registros de la tabla. Al igual que en las pasadas ocasiones, emplearemos LINQ para aplicar la condición de filtro.

[EnableClientAccess()]
public class NorthwindService : LinqToSqlDomainService<NorthwindDataContext>
{
    //....
    public IQueryable<Order> GetOrdersCiudadEntrega(string sCiudadEntrega)
    {
        return this.Context.Orders.Where(oOrder => oOrder.ShipCountry == sCiudadEntrega);
    }
    //....

Después de generar nuevamente la solución, en el code-behind de la página Silverlight crearemos un manipulador para el evento SelectionChanged del ComboBox. Dentro del código de este manipulador, la primera acción será limpiar la colección de entidades Orders, ya que cada vez que hagamos una nueva carga de datos, la colección de valores que hubiera previamente no será eliminada de forma automática.

A continuación invocaremos al nuevo método que hemos creado para cargar los registros de Orders filtrados por ciudad. Debido a que la lista de elementos del ComboBox es una colección de objetos de tipo PaisesPedido, tendremos que hacer una operación de type-casting sobre el elemento seleccionado (ComboBox.SelectedItem), para obtener el valor de su propiedad ShipCountry.

Finalmente, asignaremos al DataGrid la colección de entidades de tipo Order, que se habrán cargado en la colección Orders del contexto de dominio.

//....
public MainPage()
{
    InitializeComponent();

    oNorthwindContext.Load(oNorthwindContext.GetPaisesPedidosOrdenadosQuery());
    this.cboPaises.ItemsSource = oNorthwindContext.PaisesPedidos;

    this.cboPaises.SelectionChanged += new SelectionChangedEventHandler(cboPaises_SelectionChanged);
}

void cboPaises_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    oNorthwindContext.Orders.Clear();
oNorthwindContext.Load(oNorthwindContext.GetOrdersCiudadEntregaQuery(((PaisesPedido)this.cboPaises.SelectedItem).ShipCountry));
    this.grdDatos.ItemsSource = oNorthwindContext.Orders;
}
//....

La siguiente imagen muestra el resultado obtenido. 

 

Visualizando la tabla Orders al completo en el DataGrid

Llegados al punto actual podríamos dar por concluido el ejemplo, pero existe un pequeño aspecto de la aplicación que podemos retocar para hacer que mejore su funcionalidad.

En su estado actual, nuestra aplicación permite seleccionar y presentar los registros de la tabla Orders, filtrados por el campo ShipCountry, pero es posible que en alguna ocasión también nos interese visualizar todos los registros de la tabla, lo que actualmente no es posible.

Para solucionar este pequeño inconveniente, vamos a eliminar de la base de datos la vista PaisesPedidos, creándola nuevamente con la siguiente sentencia.

CREATE VIEW PaisesPedidos
AS
SELECT DISTINCT ShipCountry FROM Orders
UNION
SELECT '----' AS ShipCountry

De esta forma, cuando el usuario seleccione el elemento del ComboBox que contiene los guiones, cargaremos en el DataGrid todos los registros de la tabla Orders usando el método GetOrders del servicio de dominio. El código que realiza la carga de los datos quedará a partir de ahora como vemos a continuación.

void cboPaises_SelectionChanged(object sender, SelectionChangedEventArgs e) { oNorthwindContext.Orders.Clear(); string sShipCountry = ((PaisesPedido)this.cboPaises.SelectedItem).ShipCountry; if (sShipCountry == "----") { oNorthwindContext.Load(oNorthwindContext.GetOrdersQuery()); } else {
oNorthwindContext.Load(oNorthwindContext.GetOrdersCiudadEntregaQuery(sShipCountry)); } this.grdDatos.ItemsSource = oNorthwindContext.Orders; }

A continuación podemos observar el DataGrid visualizando todos los registros de la tabla.

 

Y tras este retoque damos por finalizado este artículo donde nos hemos introducido en el acceso a datos desde Silverlight, utilizando .NET RIA Services. Espero que os resulte de interés y utilidad. Al igual que en las anteriores entregas, el proyecto de ejemplo está disponible en los enlaces C# y VB.

Un saludo. 

4 Comentarios

  1. anonymous

    Una gran entrada. Me queda una duda:
    string sShipCountry = ((PaisesPedido)this.cboPaises.SelectedItem).ShipCountry;
    ¿De dónde sale el tipo PaisesPedido? o dicho de otra manera, si quisieramos recuperar el sender, ¿que tipo le asignaríamos a la conversión?

    Gracias por tu tiempo.

  2. anonymous

    Ya lo resolví. Es através de using SeleccionComboBox.Web; dónde reconoce el tipo.

    Gracias.

  3. lmblanco

    Hola Corsariovasco

    Gracias por tu interés en el artículo, y celebro que pudieras solucionar el problema que comentas.

    Un saludo,
    Luismi

  4. cynthiay

    Luismi, supongamos que en la tabla Order solamente tuviera un ID con el código del PAIS, y en una tabla distinta tuviera los códigos de país con su correspondiente DESCRIPCION, y que en el DataGrid quisiera mostrar algo como: PEDIDO, CLIENTE, DESCRIPCIONPAIS, cómo podría hacer esto?? es decir, el ejemplo que pongo es muy sencillo pero digamos que tengo un query un poco más complejo, que involucre varias tablas y varias criterios, cuyo resultado sean varios campos de las distintas tablas, cómo se hace esto? si en ese caso no habría como en tu ejemplo un Tipo de Datos específico como Order para definir el método de consulta como: public IQueryable GetOrdersCiudadEntrega(string sCiudadEntrega), donde retorna una lista de registros de tipo Order?? espero haberme explicado….saludos…Cyndy Rdz.

Deja un comentario

Tema creado por Anders Norén