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

En la primera entrega de este artículo acabábamos de crear el servicio de dominio de la aplicación, con los métodos para el lado servidor de la misma, que se ocupaban de interactuar con la base de datos. Si en este momento volvemos a compilar la solución, Visual Studio arrojará un error relacionado con el servicio de dominio que acabamos de crear.

 

El motivo de dicho error radica en que la entidad PaisesPedido, perteneciente al contexto de datos, carece de una clave; sin embargo, el servicio de dominio requiere que todas las entidades que expone tengan al menos una clave definida. Este problema lo solucionaremos abriendo el diseñador del modelo de datos, y asignando a la propiedad Primary Key, de la entidad PaisesPedido, el valor True.

De esta forma, al volver a compilar la aplicación ya no se producirá este error.

DomainContext. El código generado por .NET RIA Services para la capa cliente

La siguiente fase en el desarrollo de nuestro ejemplo corresponde a la interfaz de usuario. Situándonos en el proyecto Silverlight de la solución, al hacer clic en el icono Show All Files de la ventana Solution Explorer veremos que la carpeta Generated_Code contiene un archivo llamado SeleccionComboBox.Web.g.cs, en cuyo interior se encuentra el código correspondiente a las clases generadas por el servicio de dominio, pero en esta ocasión para el lado cliente de la aplicación.

 

Este código recibe también el nombre de contexto de dominio (DomainContext) y en él podemos encontrar la clase que lo representa: NorthwindContext, que hereda de la clase base DomainContext.

Dentro de NorthwindContext hallaremos las versiones cliente de los métodos de consulta del servicio de dominio. El nombre de estos métodos será igual que el existente en el lado servidor de la aplicación, pero incluyendo el sufijo Query.

public sealed partial class NorthwindContext : DomainContext
{
    //....
    public EntityQuery<Order> GetOrdersQuery()
    {
        return base.CreateQuery<Order>("GetOrders", null, false, true);
    }
    
    public EntityQuery<PaisesPedido> GetPaisesPedidosQuery()
    {
        return base.CreateQuery<PaisesPedido>("GetPaisesPedidos", null, false, true);
    }
    //....    
}

Definiendo la interfaz de usuario

La primera acción a desempeñar en la construcción de nuestra interfaz de usuario Silverlight, consistirá en añadir los controles de datos necesarios en la página XAML; en concreto, un ComboBox y un DataGrid con las columnas de la tabla Orders que queramos visualizar.

<UserControl 
    x:Class="SeleccionComboBox.MainPage"
    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" 
    xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot">
        <StackPanel Background="LightGreen">
            <ComboBox Name="cboPaises" Width="200" DisplayMemberPath="ShipCountry" Margin="5" />
            <data:DataGrid Name="grdDatos" 
                           Width="600" Height="370" 
                           AutoGenerateColumns="False" IsReadOnly="True">
                <data:DataGrid.Columns>
                    <data:DataGridTextColumn Header="Pedido" Binding="{Binding OrderID}" />
                    <data:DataGridTextColumn Header="Cliente" Binding="{Binding CustomerID}" />
                    <data:DataGridTextColumn Header="Destinatario" Binding="{Binding ShipName}" />
                    <data:DataGridTextColumn Header="País entrega" Binding="{Binding ShipCountry}" />
                    <data:DataGridTextColumn Header="Ciudad entrega" Binding="{Binding ShipCity}" />
                </data:DataGrid.Columns>
            </data:DataGrid>
        </StackPanel>
    </Grid>
</UserControl>

Pasando seguidamente al code-behind de esta página, la primera operación que debemos realizar será durante la carga de la misma, y se basará en rellenar el ComboBox con la lista de países obtenidos de la vista PaisesPedidos. Para ello, crearemos una instancia del contexto de dominio (clase NorthwindContext) con un ámbito que sea accesible a todo el código de la página XAML. A continuación, en el constructor de la página, llamaremos al método Load del contexto de dominio, pasándole como parámetro el método GetPaisesPedidosQuery, también de este mismo contexto, que devuelve las entidades resultantes de ejecutar la vista de la base de datos. Finalmente, asignamos como fuente de datos para el ComboBox, la propiedad PaisesPedidos del contexto de dominio, que contendrá la colección de entidades, una vez que el método NorthwindContext.Load haya finalizado.

//....
using SeleccionComboBox.Web;

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

        public MainPage()
        {
            InitializeComponent();

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

En la siguiente imagen podemos ver el ComboBox en tiempo de ejecución, mostrando la lista de valores obtenidos de la base de datos.

¿Cuándo se completa la carga de entidades en el lado cliente?

Debemos tener en cuenta que la ejecución de NorthwindContext.Load se produce de modo asíncrono (que es el modo de ejecución en el que Silverlight trabaja con servicios), por lo que la asignación a la propiedad cboPaises.ItemsSource, no significa que el control ComboBox pueda mostrar inmediatamente la lista de valores.

Si deseamos saber el momento exacto en el que la operación de carga se ha completado, para así poder empezar a utilizar el ComboBox, debemos utilizar una técnica consistente en obtener, a partir del método DomainContext.Load, el tipo genérico LoadOperation<T> que dicho método devuelve, y que representa a la operación de carga de datos; creando a continuación un manipulador para el evento Completed del objeto LoadOperation. Lo primero que haremos será añadir en el código XAML un TextBlock, que utilizaremos para informar al usuario del momento a partir del cual puede usar el ComboBox.

<!--....-->
<StackPanel Background="LightGreen">
    <TextBlock Name="txtAviso" Text="" Margin="5" HorizontalAlignment="Center" />
    <ComboBox Name="cboPaises" Width="200" DisplayMemberPath="ShipCountry" Margin="5" />
    <!--....-->

A continuación, desde el code-behind de la página, recogeremos el valor devuelto por la llamada al método NorthwindContext.GetPaisesPedidosQuery: el objeto LoadOperation<PaisesPedido>. De este objeto crearemos un manipulador para su evento Completed, el cual, al ser ejecutado, asignará un mensaje de aviso al TextBlock de la interfaz de usuario.

//....
using SeleccionComboBox.Web;
using System.Windows.Ria.Data;

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

        public MainPage()
        {
            InitializeComponent();

            LoadOperation<PaisesPedido> oLoadOperation = oNorthwindContext.Load(oNorthwindContext.GetPaisesPedidosQuery());
            oLoadOperation.Completed += new EventHandler(oLoadOperation_Completed);
            this.cboPaises.ItemsSource = oLoadOperation.Entities;
        }

        void oLoadOperation_Completed(object sender, EventArgs e)
        {
            this.txtAviso.Text = "ComboBox Cargado!!!!";
        }
    }
}

Observe el lector, que para poder utilizar la clase LoadOperation<T>, debemos declarar en el archivo de código el espacio de nombres System.Windows.Ria.Data. Por otro lado, para asignar al ComboBox los valores a mostrar emplearemos la propiedad LoadOperation<T>.Entities, que será la que contenga la colección entidades una vez completado el proceso de carga.

Finalizamos aquí la segunda parte de este artículo. En la tercera y última entrega explicaremos la forma de ordenar la lista de elementos del ComboBox, así como la carga de datos en el DataGrid con los registros de la tabla Orders. El ejemplo completo está disponible en los siguientes enlaces: C# y VB.

Un saludo. 

1 Comentario

  1. lmblanco

    Hola Enrique

    Muchas gracias por tu opinión, me alegra que te haya gustado, y a ver si hago un rato para el tema del Datawarehouse 😎

    Un saludo,
    Luismi

Deja un comentario

Tema creado por Anders Norén