Acceso a datos en Silverlight mediante DomainDataSource

Al igual que el resto de elementos de la interfaz de usuario en una aplicación Silverlight, el control DomainDataSource se define declarativamente utilizando código XAML. No obstante, también será posible implementar determinados aspectos de su comportamiento desde code behind, como veremos en la aplicación de ejemplo que vamos a desarrollar.

Por otro lado, se trata de un control que no se limita simplemente a presentar los datos obtenidos desde el contexto de dominio, sino que está dotado de una serie de características adicionales que le permiten ordenar, filtrar, agrupar, etc. dichos datos.

 

Un ejemplo demostrativo

Con la finalidad de ilustrar las anteriormente mencionadas características en el uso del control DomainDataSource, vamos a crear en Visual Studio 2010 un nuevo proyecto de tipo Silverlight Business Application (disponible en http://www.dotnetmania.com), al que daremos el nombre PruebasDDS. El motivo de utilizar este tipo de proyecto radica en que nos proporciona cierta infraestructura de la interfaz de usuario ya preparada, como es la posibilidad de tener varias páginas en la aplicación, realizando la navegación entre las mismas, lo que aprovecharemos para explicar cada uno de los aspectos del DomainDataSource en páginas distintas del proyecto.

Para adaptar esta interfaz prefabricada a nuestras necesidades, acomodando los estilos y recursos asignados a tipos de letra, literales, controles, etc., debemos editar el archivo de estilos Styles.xaml, situado en la carpeta Assets de la estructura del proyecto; y el archivo de recursos ApplicationStrings.resx situado en la carpeta Assets/Resources. Cuando necesitemos añadir nuevas páginas al proyecto lo haremos dentro de la carpeta Views (figura 1).

AccesoDatosSilverlightMedianteDomainDataSource_01

Figura 1. Estructura de carpetas del proyecto.

 

Por otro lado, esta plantilla de proyecto también proporciona ya activado el soporte de WCF RIA Services [1], necesario para la interacción de los datos entre las capas cliente e intermedia de la aplicación [2]. Como requisito previo, necesitaremos tener instalado Silverlight 4 Tools for Visual Studio 2010 [3]. En cuanto a los datos de ejemplo, utilizaremos la base de datos Chinook [4], que podemos descargar desde CodePlex.

La primera tarea a realizar será la creación, en el proyecto Web de nuestra solución, de un ADO.NET Data Model (modelo de datos) con el nombre ChinookModel, donde a partir de la tabla Invoice de la base de datos, se generará una entidad del mismo nombre. A continuación crearemos un Domain Service Class (servicio de dominio) con el nombre ChinookDomainService, que configuraremos para que genere el código para las operaciones CRUD sobre la entidad Invoice. Estas operaciones de creación se explican con más detalle en [2].

 

Obtención, presentación y actualización de datos

La principal tarea a cargo del control DomainDataSource consiste en obtener una colección de entidades desde el contexto de dominio mediante la llamada a uno de sus métodos. Una vez obtenida la colección, aplicaremos en los elementos de la interfaz de usuario expresiones de enlace a datos (data binding), para conseguir visualizar en dichos elementos los valores de las entidades.

Comenzaremos, como indica el título de este apartado, por las operaciones elementales de recuperación, visualización y edición de datos. Para ello, añadiremos al proyecto una página con el nombre Presentacion.xaml, a la que accederemos desde la página principal de la aplicación (MainPage.xaml) utilizando un control HyperlinkButton, como vemos en el listado 1.

<HyperlinkButton x:Name=”lnkPresentacion”
Style={StaticResource LinkStyle}
NavigateUri=/Presentacion”
TargetName=”ContentFrame”
Content={Binding Path=ApplicationStrings.PresentacionPageTitle, Source={StaticResource ResourceWrapper}}/>

Listado 1.

 

Dentro del diseñador de la página Presentacion.xaml arrastraremos un DomainDataSource y un DataGrid desde la Caja de Herramientas, asignándoles respectivamente, los nombres ddsInvoices y grdInvoices. Debido a que el DomainDataSource necesita acceder al contexto de dominio, tenemos que especificar declarativamente dicho dominio añadiendo un espacio de nombres (xmlns) con el nombre domainctx, en la etiqueta UserControl de la página.

Pasando a la configuración del control DomainDataSource, la propiedad QueryName contendrá el nombre del método perteneciente al servicio de dominio (GetInvoices), que devuelve la colección de entidades al contexto de dominio, y este a su vez al control. Para que el DomainDataSource tenga acceso al contexto de dominio añadiremos al código de este control la etiqueta DomainContext, especificando el espacio de nombres domainctx, declarado en la etiqueta UserControl.

Finalmente, para que el DataGrid pueda mostrar datos, asignaremos a su propiedad ItemsSource una expresión de enlace a datos que conecte este control con el DomainDataSource (listado 2). El resultado lo vemos en la figura 2.

<navigation:Page x:Class=”PruebasDDS.Views.Presentacion”
xmlns:domainctx=”clr-namespace:PruebasDDS.Web”
. . .
 
<riaControls:DomainDataSource x:Name=”ddsInvoices” QueryName=”GetInvoices”>
<riaControls:DomainDataSource.DomainContext>
<domainctx:ChinookDomainContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
 
. . .
 
<sdk:DataGrid x:Name=”grdInvoices”
ItemsSource={Binding ElementName=ddsInvoices, Path=Data}
Margin=5Height=350/>

Listado 2.

 

AccesoDatosSilverlightMedianteDomainDataSource_02

Figura 2. DataGrid visualizando los datos del DomainDataSource.

 

En tiempo de ejecución, además de consultar los datos también es posible editarlos. Una vez finalizados los cambios, podemos grabarlos en la base de datos o descartarlos mediante los métodos SubmitChanges o RejectChanges del DomainDataSource, lo que en este ejemplo llevaremos a cabo desde el evento Click de sendos controles Button (listado 3).

<Button x:Name=”btnGrabar” Content=”Grabar cambios” Width=110″ Margin=5″ Click=”btnGrabar_Click” />
 
<Button x:Name=”btnDeshacer” Content=”Deshacer cambios” Width=110″ Margin=5″ Click=”btnDeshacer_Click” />
private void btnGrabar_Click(object sender, RoutedEventArgs e)
{
this.ddsInvoices.SubmitChanges();
}
 
private void btnDeshacer_Click(object sender, RoutedEventArgs e)
{
this.ddsInvoices.RejectChanges();
}

Listado 3.

 

Ordenación

La siguiente característica que abordaremos del DomainDataSource será la capacidad de ordenar sus datos, para lo que añadiremos una nueva página al proyecto con el nombre Ordenacion.xaml, en la que al igual que en el caso anterior (y en los próximos ejemplos) añadiremos un DomainDataSource y un DataGrid, pero en esta ocasión reduciremos el número de columnas del DataGrid, creándolas manualmente dentro de la etiqueta Columns, a la que añadiremos tantos controles DataGridTextColumn como columnas necesitemos en la cuadrícula de datos. La propiedad Binding, mediante una expresión de enlace a datos, será la encargada de obtener del DomainDataSource el valor correspondiente para cada columna.

Para ordenar los datos en el DomainDataSource emplearemos la etiqueta SortDescriptors, que representa una colección de objetos SortDescriptor; este tipo de objeto contiene el modo de ordenación por uno de los campos de la colección de entidades devuelta por el DomainDataSource.

En esta parte del ejemplo ordenaremos los resultados por los campos BillingCountry, BillingCity y Total (listado 4), estableciendo también un sentido de la ordenación distinto para cada uno, mediante el atributo Direction de los objetos SortDescriptor.

<riaControls:DomainDataSource x:Name=”ddsInvoices” QueryName=”GetInvoices” AutoLoad=”True”>
  <riaControls:DomainDataSource.DomainContext>
    <domainctx:ChinookDomainContext />
  </riaControls:DomainDataSource.DomainContext> 
 
  <riaControls:DomainDataSource.SortDescriptors>
    <riaControls:SortDescriptor PropertyPath=”BillingCountry” Direction=”Descending” />
    <riaControls:SortDescriptor PropertyPath=”BillingCity” Direction=”Ascending” />
    <riaControls:SortDescriptor PropertyPath=”Total” Direction=”Descending” />
  </riaControls:DomainDataSource.SortDescriptors>
</riaControls:DomainDataSource>
 
. . .
 
<sdk:DataGrid x:Name=”grdInvoices”
ItemsSource={Binding ElementName=ddsInvoices, Path=Data}
AutoGenerateColumns=”False” Margin=5Height=350″> 
  <sdk:DataGrid.Columns>
    <sdk:DataGridTextColumn Header=”Factura” Binding={Binding InvoiceId}/>
    <sdk:DataGridTextColumn Header=”Cliente” Binding={Binding CustomerId}/>
    <sdk:DataGridTextColumn Header=”País” Binding={Binding  BillingCountry}/>
    <sdk:DataGridTextColumn Header=”Ciudad” Binding={Binding BillingCity}/>
    <sdk:DataGridTextColumn Header=”Importe” Binding={Binding Total}/>
  </sdk:DataGrid.Columns>
</sdk:DataGrid>

Listado 4.

 

Apreciaremos los campos ordenados porque en su cabecera se muestra un pequeño indicador del sentido de la ordenación (figura 3). Si bien el propio control DataGrid permite por defecto ordenar una columna haciendo clic en su cabecera, la ordenación desde el DomainDataSource, como acabamos de comprobar, presenta como ventaja la posibilidad de ordenar por más de una columna simultáneamente.

AccesoDatosSilverlightMedianteDomainDataSource_03

Figura 3. DataGrid ordenado mediante el DomainDataSource.

 

Ordenando desde code behind

Aunque la programación que habitualmente realicemos con el DomainDataSource sea eminentemente declarativa, también existe la posibilidad de implementar cierto comportamiento desde code behind. Como muestra, añadiremos al diseñador de la página dos controles TextBox, dos CheckBox y un Button (listado 5), y en el evento Click de este último eliminaremos el orden establecido declarativamente en la página XAML. Seguidamente, crearemos dos nuevos objetos SortDescriptor, utilizando como campo de ordenación el valor de los TextBox, estableciendo el sentido del orden ascendente o descendente en función de si está marcado el CheckBox situado junto a cada TextBox. Finalmente, agregaremos estos objetos a la colección DomainDataSource.SortDescriptors (listado 6), con el resultado que vemos en la figura 4.

<StackPanel Width=300″ >
  <StackPanel Orientation=”Horizontal”>
    <TextBlock Text=”Orden 1″ Margin=0,2,5,0″ VerticalAlignment=”Center” />
    <TextBox x:Name=”txtOrden1″ Margin=0,2,5,0Width=100/>
    <CheckBox x:Name=”chkDescendente1″ Content=”Descendente”
    Margin=0,2,10,0″ VerticalAlignment=”Center” />
  </StackPanel> 
 
  <StackPanel Orientation=”Horizontal”>
    <TextBlock Text=”Orden 2″ Margin=0,2,5,0″ VerticalAlignment=”Center” />
    <TextBox x:Name=”txtOrden2″ Margin=0,2,5,0Width=100/>
    <CheckBox x:Name=”chkDescendente2″ Content=”Descendente”
    Margin=0,2,10,0″ VerticalAlignment=”Center” />
  </StackPanel> 
 
  <Button x:Name=”btnOrdenar” Content=”Ordenar” Margin=0,2,0,0Width=100
  HorizontalAlignment=”Center” Click=”btnOrdenar_Click” />
</StackPanel> 
 
<sdk:DataGrid x:Name=”grdInvoices”
. . .

Listado 5.

 

private void btnOrdenar_Click(object sender, RoutedEventArgs e)
{
    this.ddsInvoices.SortDescriptors.Clear();
 
    SortDescriptor oSortDesc1 = new SortDescriptor(this.txtOrden1.Text, 
        this.chkDescendente1.IsChecked.Value ? System.ComponentModel.ListSortDirection.Descending : 
        System.ComponentModel.ListSortDirection.Ascending);
 
    this.ddsInvoices.SortDescriptors.Add(oSortDesc1);
 
    SortDescriptor oSortDesc2 = new SortDescriptor(this.txtOrden2.Text,
        this.chkDescendente2.IsChecked.Value ? System.ComponentModel.ListSortDirection.Descending : 
        System.ComponentModel.ListSortDirection.Ascending);
 
    this.ddsInvoices.SortDescriptors.Add(oSortDesc2);
}

Listado 6.

 

AccesoDatosSilverlightMedianteDomainDataSource_04

Figura 4. Ordenación mediante controles de la página.

 

Filtros

Si necesitamos establecer una condición sobre los datos devueltos por el DomainDataSource, de modo que sólo visualicemos un subconjunto de los mismos, aplicaremos sobre este control uno o varios filtros, representados por la clase (etiqueta XAML) FilterDescriptor, asignando a su propiedad PropertyPath el nombre del campo sobre el que se aplicará el filtro; la propiedad Value contendrá el valor del filtro, mientras que con la propiedad Operator (tipo enumerado FilterDescriptorLogicalOperator) estableceremos el modo de aplicación del filtro (igual que, mayor que, menor o igual que, etc.). Todos los filtros deberán estar contenidos dentro de la etiqueta FilterDescriptors del DomainDataSource, que representa la colección de filtros creados en el control.

Para poner en práctica esta característica, después añadir una página con el nombre Filtros.xaml a nuestro proyecto y configurarla como en los anteriores casos, agregaremos una combinación de filtros por tres campos de las entidades manejadas por el DomainDataSource (listado 7).

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoices" AutoLoad="True">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.FilterDescriptors>
        <riaControls:FilterDescriptor PropertyPath="BillingCountry" Operator="IsEqualTo" Value="Canada" />
        <riaControls:FilterDescriptor PropertyPath="BillingCity" Operator="IsContainedIn" Value="Halifax,Ottawa" />
        <riaControls:FilterDescriptor PropertyPath="Total" Operator="IsLessThan" Value="5" />
    </riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>

Listado 7.

 

Al poner en ejecución esta página, comprobaremos la efectividad del código que acabamos de escribir, ya que el número de registros mostrados por el DataGrid se reducirá a las condiciones establecidas en los filtros (figura 5).

AccesoDatosSilverlightMedianteDomainDataSource_05

Figura 5. Datos filtrados mediante el DomainDataSource.

 

Como hemos comprobado, existen diversos modos de combinar los filtros y sus propiedades, a fin de acotar los resultados devueltos por el DomainDataSource: un filtro único, varios filtros sobre distintos campos, una colección de valores separados por comas, etc. Pero supongamos que necesitamos crear un filtro sobre un mismo campo numérico que contemple varios valores; si intentamos poner dichos valores en una lista separada por comas obtendremos un error, aunque esto no significa que no podamos establecer dicho filtro, ya que la solución estriba en emplear un filtro independiente por cada valor, añadiendo en la declaración del control DomainDataSource el valor Or al atributo FilterOperator (listado 8).

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoices" FilterOperator="Or" AutoLoad="True">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.FilterDescriptors>                
        <riaControls:FilterDescriptor PropertyPath="Total" Operator="IsEqualTo" Value="3,96" />
        <riaControls:FilterDescriptor PropertyPath="Total" Operator="IsEqualTo" Value="7,92" />
        <riaControls:FilterDescriptor PropertyPath="Total" Operator="IsEqualTo" Value="10,90" />
    </riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>

Listado 8.

 

No obstante, los ejemplos anteriores resultan muy rígidos, ya que establecen un valor fijo para el filtro sin poder cambiarlo, mientras que lo deseable en este tipo de situación sería dar al usuario la posibilidad de introducir dicho valor.

Podemos lograr este comportamiento desde el code behind de la página, como vimos en la ordenación de datos; sin embargo, en este caso optaremos por una solución distinta, pero igualmente efectiva (listado 9), consistente en enlazar la propiedad FilterDescriptor.Value con un control de la página que sea el que proporcione el valor de filtro, por ejemplo, un TextBox; empleando el operador de filtro StartsWith, para que los datos sean filtrados dinámicamente según escribimos (figura 6).

<riaControls:DomainDataSource.FilterDescriptors>
    <riaControls:FilterDescriptor PropertyPath="BillingCity" 
                                    Operator="StartsWith" 
                                    Value="{Binding ElementName=txtBillingCity, Path=Text}" />
</riaControls:DomainDataSource.FilterDescriptors>
....
<StackPanel Orientation="Horizontal" Margin="5">
    <TextBlock Text="Ciudad:" VerticalAlignment="Center" />
    <TextBox x:Name="txtBillingCity" Width="200" />
</StackPanel>
....
<sdk:DataGrid x:Name="grdInvoices" 
....

Listado 9.

 

AccesoDatosSilverlightMedianteDomainDataSource_06

Figura 6. Filtrando desde un control de la página.

 

Agrupaciones de datos

Mediante el uso combinado de la colección GroupDescriptors y objetos GroupDescriptor, podemos agrupar los datos del DomainDataSource en base a un campo de la colección de entidades de este último, de forma que en el DataGrid, todos los registros con el mismo valor para el campo de agrupamiento muestren una fila en la cuadrícula de datos a modo de cabecera para dicho campo; al hacer clic en esa fila de cabecera se contraerán o expandirán las filas dependientes (figura 7). Para conseguir esta funcionalidad, al declarar el grupo en el código de la página XAML, asignaremos el nombre del campo utilizando la propiedad GroupDescriptor.PropertyPath. Todas estas operaciones las realizaremos añadiendo una página al proyecto con el nombre Grupos.xaml (listado 10).

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoices" AutoLoad="True">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.GroupDescriptors>
        <riaControls:GroupDescriptor PropertyPath="BillingCountry" />
    </riaControls:DomainDataSource.GroupDescriptors>
</riaControls:DomainDataSource>

Listado 10.

 

AccesoDatosSilverlightMedianteDomainDataSource_07

Figura 7. Datos agrupados en el DataGrid mediante el DomainDataSource.

 

Si añadimos varios objetos GroupDescriptor (listado 11) conseguiremos un agrupamiento anidado a varios niveles (figura 8).

<riaControls:DomainDataSource.GroupDescriptors>
    <riaControls:GroupDescriptor PropertyPath="BillingCountry" />
    <riaControls:GroupDescriptor PropertyPath="BillingCity" />
</riaControls:DomainDataSource.GroupDescriptors>

Listado 11.

 

AccesoDatosSilverlightMedianteDomainDataSource_08

Figura 8. Grupos anidados.

 

También podemos realizar la operación de expandir/contraer los grupos desde code behind, lo cual confiere a nuestra aplicación una mayor flexibilidad. Si por ejemplo añadimos un CheckBox a la página (listado 12), en su evento Click (listado 13) obtenemos, de la propiedad DomainDataSource.Data, los datos en forma de tipo ICollectionView. Recorriendo la colección ICollectionView.Groups, por cada uno de los objetos CollectionViewGroup que contiene, podemos expandir o contraer el grupo en el DataGrid llamando a los métodos CollapseRowGroup o ExpandRowGroup de este control, pasándoles como parámetro el objeto CollectionViewGroup. Previamente ejecutaremos el método DataGrid.ScrollIntoView para posicionarnos en el grupo requerido (figura 9).

<CheckBox x:Name="chkContraer" 
            Content="Contraer grupos" 
            HorizontalAlignment="Center"
            Margin="5" 
            Click="chkContraer_Click" />

Listado 12.

private void chkContraer_Click(object sender, RoutedEventArgs e)
{
    ICollectionView oCollectionView = (ICollectionView)this.ddsInvoices.Data;
 
    if ((bool)this.chkContraer.IsChecked)
    { 
        foreach (CollectionViewGroup  oCollectionViewGroup in oCollectionView.Groups)
        {
            this.grdInvoices.ScrollIntoView(oCollectionViewGroup, null);
            this.grdInvoices.CollapseRowGroup(oCollectionViewGroup, true);
        }
    }
    else
    {
        foreach (CollectionViewGroup oCollectionViewGroup in oCollectionView.Groups)
        {
            this.grdInvoices.ScrollIntoView(oCollectionViewGroup, null);
            this.grdInvoices.ExpandRowGroup(oCollectionViewGroup, true);
        }
    }
}

Listado 13.

 

AccesoDatosSilverlightMedianteDomainDataSource_09

Figura 9. DataGrid con todos los grupos contraídos.

 

Selección mediante parámetros

Además del código generado automáticamente por el servicio de dominio, podemos escribir nuestros propios métodos en dicho servicio, que retornen los datos en función de los parámetros que reciban, por lo que necesitamos disponer en el DomainDataSource de algún tipo de mecanismo, que nos permita enviar los valores de tales parámetros cuando el método a utilizar en este control así lo requiera.

Para crear un parámetro utilizaremos la clase Parameter, asignando a la propiedad ParameterName el nombre del parámetro perteneciente al método, mientras que en la propiedad Value asignaremos el valor que recibirá el parámetro. Los parámetros tendrán que estar contenidos dentro de la colección DomainDataSource.QueryParameters.

Para ilustrar el uso de parámetros mediante un ejemplo, añadiremos al servicio de dominio el método GetInvoicesBillingCountry (listado 14), que recibe un parámetro con el que devuelve las entidades Invoice que tengan dicho valor en la propiedad BillingCountry.

public IQueryable<Invoice> GetInvoicesBillingCountry(string sBillingCountry)
{
    return this.ObjectContext.Invoices.Where(oInvoice => oInvoice.BillingCountry == sBillingCountry);
}

Listado 14.

 

A continuación añadiremos al proyecto la página Parametros.xaml, agregando a esta un DomainDataSource con el nombre del método recién creado en la propiedad QueryName, y la definición de un parámetro para dicho método (listado 15). Los datos resultantes se ajustarán al valor del parámetro (figura 10).

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoicesBillingCountry" AutoLoad="True">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.QueryParameters>
        <riaControls:Parameter ParameterName="sBillingCountry" Value="Canada" />
    </riaControls:DomainDataSource.QueryParameters>
</riaControls:DomainDataSource>

Listado 15.

 

AccesoDatosSilverlightMedianteDomainDataSource_10

Figura 10. Datos resultantes del método parametrizado.

 

Por otro lado, al igual que ocurre en los filtros, mediante una expresión de enlace a datos (listado 16) podemos conseguir que el usuario, a través de un control de la página, sea quien introduzca el valor del parámetro (figura 11).

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoicesBillingCountry" AutoLoad="True">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.QueryParameters>
        <riaControls:Parameter ParameterName="sBillingCountry" 
                               Value="{Binding ElementName=txtBillingCountry,Path=Text}" />
    </riaControls:DomainDataSource.QueryParameters>
</riaControls:DomainDataSource>
....
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
    <TextBlock Text="País" Margin="5" />
    <TextBox x:Name="txtBillingCountry" Width="200" Margin="5" />
</StackPanel>

Listado 16.

 

AccesoDatosSilverlightMedianteDomainDataSource_11

Figura 11. Envío del parámetro desde un control de la página.

 

Paginación

Si tenemos que trabajar con una cantidad considerable de entidades, resultará recomendable su visualización paginada en el DataGrid, facilitando así la consulta al usuario. No obstante, el trabajo con este modo de visualización no depende única y exclusivamente del DataGrid, sino que también recae sobre el DomainDataSource y el control DataPager. Para aplicar esta característica en el proyecto de ejemplo añadiremos una nueva página llamada Paginacion.xaml.

En las propiedades PageSize y LoadSize (listado 17), pertenecientes al DomainDataSource, estableceremos respectivamente la cantidad de elementos a mostrar por página y la cantidad de elementos a cargar. El DataPager se encargará de proporcionar la interfaz de usuario para navegar por las páginas mostradas en el DataGrid. Precisamente por el hecho de utilizar el DataPager, hemos de definir un orden en el DomainDataSource para que la paginación funcione adecuadamente, debido a que Entity Framework no soporta paginación si no tiene establecido previamente un orden sobre los datos.

<riaControls:DomainDataSource x:Name="ddsInvoices" QueryName="GetInvoices" AutoLoad="True" PageSize="10" LoadSize="30">
    <riaControls:DomainDataSource.DomainContext>
        <domainctx:ChinookDomainContext />
    </riaControls:DomainDataSource.DomainContext>
 
    <riaControls:DomainDataSource.SortDescriptors>
        <riaControls:SortDescriptor PropertyPath="InvoiceId" />
    </riaControls:DomainDataSource.SortDescriptors>
</riaControls:DomainDataSource>
....
<sdk:DataGrid x:Name="grdInvoices" 
....
<sdk:DataPager x:Name="pgrInvoices" 
               Source="{Binding ElementName=ddsInvoices,Path=Data}" 
               Width="200" />

Listado 17.

 

AccesoDatosSilverlightMedianteDomainDataSource_12

Figura 12. Paginación de datos.

 

Conclusiones

En este artículo hemos abordado los principales aspectos del DomainDataSource, un interesante componente de WCF RIA Services, que facilita la interacción con los datos entre la interfaz de usuario y el servicio/contexto de dominio de la aplicación. Para aquellos lectores interesados en seguir profundizando en todos los aspectos de su funcionamiento, les recomendamos visitar el blog de Jeff Handley [5], uno de los principales miembros del equipo de desarrollo.

 

REFERENCIAS

[1] WCF RIA Services.

https://www.silverlight.net/getstarted/riaservices/

[2] Blanco, Luis Miguel. “Acceso a datos en Silverlight con WCF RIA Services”.

[3] Silverlight 4 Tools for Visual Studio 2010 y Silverlight Toolkit.

https://www.silverlight.net/getstarted/

[4] Base de datos Chinook.

http://chinookdatabase.codeplex.com/

[5] Blog de Jeff Handley.

http://jeffhandley.com/

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *