Paging with the Silverlight RIA services DomainDataSource

Using the declarative DomainDataSource that is part of the upcoming Silverlight 3 RIA services makes it quite easy to work with data. All you need to do is add a DomainDataSource control to the the XAML, point it to the generated DomainContext class (in this case NorthwindContext) and tell it which method to use to load the data from the web service(in this case LoadCustomers). Next add a DataGrid to display the data and you are good to go.

<UserControl xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"  x:Class="LOBUsingRIAServices.CustomerListPage"


             xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  


             xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"


             xmlns:web="clr-namespace:LOBUsingRIAServices.Web"


             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 


             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <Grid x:Name="LayoutRoot" Background="White">


        <riaControls:DomainDataSource x:Name="CustomerDataSource"


                                      LoadMethodName="LoadCustomers">


            <riaControls:DomainDataSource.DomainContext>


                <web:NorthwindContext />


            </riaControls:DomainDataSource.DomainContext>


        </riaControls:DomainDataSource>


        <data:DataGrid ItemsSource="{Binding Data, ElementName=CustomerDataSource}" />


    </Grid>


</UserControl>

 

Pretty simple and that is the way I like it [:)]

Adding paging.

Sometimes the lost of data to load can get somewhat large and you might not want to load all data. In that case all you need to do is add a PageSize and the DomainDataSource will only load enough data to display on a single page. You can do this by just setting the PageSize on the DomainDataSource but as we also need a control to allow the user to page trough the data it is easier to also add the DataPager control. Now you have the option of setting the PageSize on the DomainDataSource or the DataPager. I found that setting it on either would work just was well except for the initial load where the DataPager shows page 0 when the PageSize is set on the DomainDataSource while it is set to 1, the correct value, when set on the DataPager. I assume this is just a small bug in the current preview.

Another thing you can specify is the LoadSize. This determines how many rows are loaded with each request and if not set equals the PageSize. Setting this to double the PageSize will improve the responsiveness of the the client application so might be a good idea if the data isn’t too large.

<UserControl xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"  x:Class="LOBUsingRIAServices.CustomerListPage"


             xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  


             xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"


             xmlns:web="clr-namespace:LOBUsingRIAServices.Web"


             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 


             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <Grid x:Name="LayoutRoot" Background="White">


        <riaControls:DomainDataSource x:Name="CustomerDataSource"


                                      LoadMethodName="LoadCustomers"


                                      LoadSize="40">


            <riaControls:DomainDataSource.DomainContext>


                <web:NorthwindContext />


            </riaControls:DomainDataSource.DomainContext>


        </riaControls:DomainDataSource>


        <data:DataGrid ItemsSource="{Binding Data, ElementName=CustomerDataSource}" />


        <dataControls:DataPager Source="{Binding Data, ElementName=CustomerDataSource}" 


                                PageSize="20" />


    </Grid>


</UserControl>

The DataPager control is quite easy to use as well. Just drop it below the DataGrid and point it to the DomainDataSource to use and it just works. One problem I ran into was adding the DataPager above the DataGrid though. When I did that the DataPager didn’t show up on the UI so the user could not page through the data even though it still limited the data to the first page.

 

Using progressive loading

Another nice option is delayed loading. When using progressive loading all you need to do is specify the LoadSize on the DomainDataSource. The DomainDataSource will now load the specified number of rows, wait a bit and load the next set of rows. It will keep on doing this until all data is loaded. The nice thing here is that all the data is loaded but the UI still stays responsive for the user. De the default interval between load requests is 0.75 seconds but this can be fine tuned using the LoadDelay time span on the DomainDataSource.

<UserControl xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"  x:Class="LOBUsingRIAServices.CustomerListPage"


             xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  


             xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"


             xmlns:web="clr-namespace:LOBUsingRIAServices.Web"


             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 


             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <Grid x:Name="LayoutRoot" Background="White">


        <riaControls:DomainDataSource x:Name="CustomerDataSource"


                                      LoadMethodName="LoadCustomers"


                                      LoadSize="10"


                                      LoadDelay="0:0:0.25">


            <riaControls:DomainDataSource.DomainContext>


                <web:NorthwindContext />


            </riaControls:DomainDataSource.DomainContext>


        </riaControls:DomainDataSource>


        <data:DataGrid ItemsSource="{Binding Data, ElementName=CustomerDataSource}" />


    </Grid>


</UserControl>



 



And all of this was done without writing any code add everything was completely declarative. Of course it is just a matter of setting properties so doing so from code is easy enough.



 



Enjoy!

26 thoughts on “Paging with the Silverlight RIA services DomainDataSource

  1. Hi Maurice,

    I am trying the and
    on a single table with with composite primary key.

    I am setting the DomainDataSource LoadSize=”20″
    DataPage PageSize=”10″

    When the page loaded, I was able to Navigate to Page 1 and Page 2 and When I click on the Page 3 which the pager now request information from the server, nothing come back.

    I have tested on SQL 2005 and SQL 2008 but both return nothing. Are you aware of any bug in the above scenario?

    Step taken:
    1. Create ADO.NET Entity Data Model on 1 table.
    2. Create Domain Service Class on the above step 1
    3. Adding Domain Data Source calling Domain Service Method.
    4. Binding Domain Data Source to the Data Pager.

    Am I missing something?

    Thank your for your help!

  2. Further to my previous Comments:

    I’ve found that the DataPager returned the error message but because it does not throw to silverlight by default.

    Form discussion (Exception from RIA services not making it from ASP.Net server to SL client) at:
    http://silverlight.net/forums/t/97140.aspx

    I have follow the instruction on the discussion and turn off customerror and create code behind to throw exception.

    The Exception Message is:
    System.Windows.Ria.Data.EntityOperationException: The method ‘Skip’ is only supported for sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before the method ‘Skip’.

    Look like I found a Bug?

  3. Found the Solution.

    When I look at the sample code from Brad Abrams the NorthwindDomainService (GetSuperEmployees())

    It contains
    return this.Context.SuperEmployeeSet
    .Where(emp=>emp.Issues>100)
    .OrderBy(emp=>emp.EmployeeID);

    whereas my just contain a single statement.
    like:
    return this.Context.SuperEmployeeSet;

    I have added in .OrderBy(emp=>emp.EmployeeID) and the datapager control is working.

    I think this is definitely a bug ( I am not sure where to report this).

  4. I have the same problem as the first poster. I dowloaded the example/demo application using the “AdventureWorks.mdf” and the Entity Framework and it works fine (of course it has the domaindatasource.filterdescription). So I did the same steps as was outlined in the WalkthroughMIX.doc, except I am using sql 2005 and no filters, and when I went to page 3, nothing. How do we make Microsoft aware of this? Did Microsoft only get this working for the demo. What are people doing who are using Silverlight 3 in production?

  5. Remember that Silverlight 3 is still in beta and won’t be “launched” until July 10th, so hopefully noone is using it in production. I’m guessing the issue you’re running into is EF-related, because I’m using Linq to SQL and it works fine.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>