Silverlight 4.0: Sorting and Grouping Data with DomainDataSource

This article gives a complete idea of the sorting and grouping features available with the “DomainDataSource” control in Silverlight (using WCF RIA Services). It discusses both markup and code-behind methodologies to implement sorting and grouping against data retrieved from WCF RIA Services.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 6
August 30, 2010
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

To make this article simple, I built a simple Silverlight 4.0 application which consumes a WCF RIA Service created using the WCF RIA Service Library. If you are not familiar with developing applications using the WCF RIA Service Library and Silverlight 4.0, check out a beginner’s article.

If you are unfamiliar with “DomainDataSource,” I strongly recommend that you go through my previous articles published at http://www.aspfree.com/cp/bio/Jagadish-Chatarji

The entire source code for this article is available in the form of a free downloadable zip file.  The solution was developed using Microsoft Visual Studio 2010 Ultimate Edition with Microsoft Silverlight 4.0 on Windows 7 Ultimate edition.  I didn’t really test it in any other environment.  I request that you post in the discussion area if you have any problems with execution.

Sorting data using DomainDataSource – the markup way

In my previous articles, I explained the importance of DomainDataSource and how we can query data using the same in a Silverlight 4.0 application.  In this section, we will focus on sorting the data available in DomainDataSource. 

Let us start with an example:

<UserControl x:Class="SLBusinessAppWithRiaLib.DdsSorting"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.
DomainServices"
    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:local="clr-namespace:BusinessLib.Web;assembly=BusinessLib"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Width="500" Height="500">

    <UserControl.Resources>
        <riaControls:DomainDataSource x:Name="EmpDomDataSource"
                                      LoadSize="15"
                                      QueryName="GetEmps"
                                      AutoLoad="True">
            <riaControls:DomainDataSource.DomainContext>
                <local:EmpMgrDomainSvc></local:EmpMgrDomainSvc>
            </riaControls:DomainDataSource.DomainContext>
        </riaControls:DomainDataSource>
    </UserControl.Resources>
   
    <Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>

        <sdk:DataGrid
            x:Name="dgEmp"
            Margin="8" MinHeight="200" IsReadOnly="True"
            AutoGenerateColumns="True"
            ItemsSource="{Binding Data, ElementName=EmpDomDataSource}" />

    </Grid>
</UserControl>

Let's examine the code above code. I defined a DomainDataSource named “EmpDomDataSource” which works with a Domain Service context defined as “EmpMgrDomainSvc.” The DomainDataSource works with an entity query named “GetEmps” and loads all entities automatically (the “AutoLoad” setting is set to “true”).  Finally, DataGrid gets bound to DomainDataSource as shown below:

Now, it is time to implement the “sorting” feature.  Modify the DomainDataSource definition as follows:

        <riaControls:DomainDataSource x:Name="EmpDomDataSource"
                                      LoadSize="15"
                                      QueryName="GetEmps"
                                      AutoLoad="True">
            <riaControls:DomainDataSource.DomainContext>
                <local:EmpMgrDomainSvc></local:EmpMgrDomainSvc>
            </riaControls:DomainDataSource.DomainContext>
            <riaControls:DomainDataSource.SortDescriptors>
                <riaControls:SortDescriptor PropertyPath="ename" Direction="Descending" />
            </riaControls:DomainDataSource.SortDescriptors>
        </riaControls:DomainDataSource>

In the above code, we are adding a “SortDescriptor” to the “DomainDataSource” element.  The “SortDescriptor” gives us the flexibility to add sorting features to an existing “DomainDataSource.”  It mainly accepts fields on which data needs to be sorted, and the direction (ascending or descending). 

Once we execute our form after the above modification, the output should look like the following screen shot:

The code-behind way to sort data using DomainDataSource: form design

In the previous section, we saw how to sort data in DomainDataSource using a simple change in markup.  In this section, we will try to accomplish the same using code-behind.

Let us create a new form as follows:

<UserControl x:Class="SLBusinessAppWithRiaLib.DdsSortingCodeBehind"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.
DomainServices"
    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:local="clr-namespace:BusinessLib.Web;assembly=BusinessLib"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Width="500" Height="500">

    <UserControl.Resources>
        <riaControls:DomainDataSource x:Name="EmpDomDataSource"
                                      LoadSize="15"
                                      QueryName="GetEmps"
                                      AutoLoad="True">
            <riaControls:DomainDataSource.DomainContext>
                <local:EmpMgrDomainSvc></local:EmpMgrDomainSvc>
            </riaControls:DomainDataSource.DomainContext>
        </riaControls:DomainDataSource>
    </UserControl.Resources>
   
    <Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>
       
        <StackPanel Orientation="Horizontal" Margin="8,8,8,8">
            <Button x:Name="btnOrderByEname" Content="Order By Name" ></Button>
            <Button x:Name="btnOrderBySal" Content="Order By Salary"  Margin="8,0,0,0"></Button>
            <Button x:Name="btnOrderByDeptnoEname" Content="Order By Deptno, Ename"  Margin="8,0,0,0"></Button>
        </StackPanel>
       
        <sdk:DataGrid Grid.Row="1"
            x:Name="dgEmp"
            Margin="8" MinHeight="200" IsReadOnly="True"
            AutoGenerateColumns="True"
            ItemsSource="{Binding Data, ElementName=EmpDomDataSource}" />

    </Grid>
</UserControl>

The design for the above code would look similar to the following screen shot:

The next section explains the code above.

The code-behind way to sort data using DomainDataSource: form design explanation

This section explains the code provided in previous section.  Let us start from here:

<Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>
.
.
</Grid>

The above markup creates a grid layout with two rows. The first row would expand based on the content, and the second occupies the rest of the area.

<StackPanel Orientation="Horizontal" Margin="8,8,8,8">
            <Button x:Name="btnOrderByEname" Content="Order By Name" ></Button>
            <Button x:Name="btnOrderBySal" Content="Order By Salary"  Margin="8,0,0,0"></Button>
            <Button x:Name="btnOrderByDeptnoEname" Content="Order By Deptno, Ename"  Margin="8,0,0,0"></Button>
        </StackPanel>

The above creates a stack panel which acts as a container to all buttons placed next to each other in a horizontal manner. From the above, you should understand that the stack panel contains three buttons sitting next to each other.

        <sdk:DataGrid Grid.Row="1"
            x:Name="dgEmp"
            Margin="8" MinHeight="200" IsReadOnly="True"
            AutoGenerateColumns="True"
            ItemsSource="{Binding Data, ElementName=EmpDomDataSource}" />

Finally, we have DataGrid, which sits in the second row of the whole form. This occupies the rest of the space after the first row (with stack panel) is rendered. It is currently bound to “EmpDomDataSource,” which is defined as follows:

    <UserControl.Resources>
        <riaControls:DomainDataSource x:Name="EmpDomDataSource"
                                      LoadSize="15"
                                      QueryName="GetEmps"
                                      AutoLoad="True">
            <riaControls:DomainDataSource.DomainContext>
                <local:EmpMgrDomainSvc></local:EmpMgrDomainSvc>
            </riaControls:DomainDataSource.DomainContext>
        </riaControls:DomainDataSource>
    </UserControl.Resources>

As of now, the above simply defines a DomainDataSource, which pulls information from entity query “GetEmps.”  It does not do any sorting yet.

The code for the buttons is provided in the next section.

The code-behind way to sort data using DomainDataSource: code

This section contains the code-behind for the button discussed in the previous section.

Modify your code-behind so that it looks similar to the following:

Imports System.ServiceModel.DomainServices.Client
Imports System.Windows.Data

Partial Public Class DdsSortingCodeBehind
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub


    Private Sub EmpDomDataSource_LoadedData(ByVal sender As Object, ByVal e As System.Windows.Controls.LoadedDataEventArgs) Handles EmpDomDataSource.LoadedData
        If e.HasError Then
            System.Windows.MessageBox.Show(e.Error.ToString, "Load Error", System.Windows.MessageBoxButton.OK)
            e.MarkErrorAsHandled()
        End If
    End Sub

    Private Sub btnOrderByEname_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnOrderByEname.Click
        Me.EmpDomDataSource.SortDescriptors.Clear()
        Me.EmpDomDataSource.SortDescriptors.Add(New SortDescriptor("ename", ComponentModel.ListSortDirection.Descending))
    End Sub

    Private Sub btnOrderBySal_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnOrderBySal.Click
        Me.EmpDomDataSource.SortDescriptors.Clear()
        Me.EmpDomDataSource.SortDescriptors.Add(New SortDescriptor("sal", ComponentModel.ListSortDirection.Descending))
    End Sub

    Private Sub btnOrderByDeptnoEname_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnOrderByDeptnoEname.Click
        Me.EmpDomDataSource.SortDescriptors.Clear()
        Me.EmpDomDataSource.SortDescriptors.Add(New SortDescriptor("deptno", ComponentModel.ListSortDirection.Descending))
        Me.EmpDomDataSource.SortDescriptors.Add(New SortDescriptor("ename", ComponentModel.ListSortDirection.Ascending))
    End Sub

End Class

The DomainDataSource element contains the “SortDescriptors” collection. We can add as many sort parameters as possible to this collection. The moment we add any object to “SortDescriptors,” DomainDataSource automatically sorts data immediately and will be reflected automatically in data grid. 

Grouping data using DomainDataSource

In all of the previous sections, we saw how to sort data using DomainDataSource.  In this section, we will see how to group data using DomainDataSource.

Let us add a new form as follows:

<UserControl x:Class="SLBusinessAppWithRiaLib.DdsGrouping"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.
DomainServices"
    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:local="clr-namespace:BusinessLib.Web;assembly=BusinessLib"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Width="500" Height="500">

    <UserControl.Resources>
        <riaControls:DomainDataSource x:Name="EmpDomDataSource"
                                      LoadSize="15"
                                      QueryName="GetEmps"
                                      AutoLoad="True">
            <riaControls:DomainDataSource.DomainContext>
                <local:EmpMgrDomainSvc></local:EmpMgrDomainSvc>
            </riaControls:DomainDataSource.DomainContext>
            <riaControls:DomainDataSource.GroupDescriptors>
                <riaControls:GroupDescriptor PropertyPath="deptno"></riaControls:GroupDescriptor>
            </riaControls:DomainDataSource.GroupDescriptors>
        </riaControls:DomainDataSource>
    </UserControl.Resources>
   
    <Grid x:Name="LayoutRoot" Background="White">
     <Grid.RowDefinitions>
      <RowDefinition Height="*" />
     </Grid.RowDefinitions>

        <sdk:DataGrid
            x:Name="dgEmp"
            Margin="8" MinHeight="200" IsReadOnly="True"
            AutoGenerateColumns="True"
            ItemsSource="{Binding Data, ElementName=EmpDomDataSource}" />

    </Grid>
</UserControl>

The above would give you the output shown in the screen shot below:

In the above code, we are working with “GroupDescriptors” (in place of “SortDescriptors” explained in previous sections). The “GroupDescriptors” element can accept any number of “GroupDescriptor” elements, and the data available in DomainDataSource automatically gets grouped at the client side based on the groupings we specify.

We did not do any code-behind in the above code. If we wanted to achieve the same in code-behind, the code would be similar to what we discussed in the previous section. We will be working with a “GroupDescriptors” collection of “DomainDataSource” objects instead of “SortDescriptors.”

My upcoming articles will focus on sorting, grouping, filtering and paging using the “DomainDataSource” element. I hope you enjoyed the article; suggestions, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com/.

blog comments powered by Disqus
SILVERLIGHT ARTICLES

- With Silverlight Gone, Whither SharePoint?
- Silverlight in the News
- Silverlight Has a Bright Future
- Windows 8 Effects on .Net and Silverlight De...
- Microsoft`s SkyDrive Abandons Silverlight
- Silverlight Developers Unhappy with Windows ...
- Best Silverlight Examples
- How to install Silverlight for Windows Phone
- Microsoft Reveals Silverlight 5 Features
- Silverlight News: SRS and Microsoft to Bring...
- Silverlight 4.0: Paging Through Data using D...
- Silverlight 4.0: Navigating Data Using Domai...
- Silverlight 4.0: Filtering Data Using Domain...
- Silverlight 4.0: Sorting and Grouping Data w...
- Silverlight 4.0: Query Parameters of DomainD...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 5 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials