Thursday, June 4, 2009

Grouping in Silverlight 3 DataGrid

DataGrid is a very useful and powerful control whether used in a Windows or a Web application. The DataGrid control is a databound control and is a flexible way to display data in a tabular format with features like sorting, dragging column headers etc.
While using the DataGrid in Silverlight 2, a common requirement was to group similar records (For e.g. group all records of particular city together). We got a similar mail from one of our visitors Rachida, who wanted to know how to group data in the Silverlight DataGrid. Well in Silverlight 3 DataGrid, this feature has been added and now we can group records with ease. In this article, we will first explore how to group data from a static datasource. Later on, we will then connect to database and group the data from the database. This
Note: For data grouping we have to set fields name based on which we want to group data.
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB.NET) > Select ‘Silverlight’ in the Project Types > from the templates, select ‘Silverlight Application’. Type a name (DataGridGrouping) and location for the project and click OK (see Figure below).
New Project
Step 2: Choose the first option ‘Add a new Web to the solution for hosting the control’ and the project type as ‘Web Site’ and click OK. You will see that two projects are created: DataGridGrouping.Web and DataGridGrouping.
New Silverlight App
Step 3: Create a class called CompanyDetails in our codebehind file MainPage.xaml.cs. The class will have the following properties: Company Name, Location, EmployeeAge, EmloyeeFirstName and EmployeeLastName. We will use List as datasource of DataGrid control. The class will look like this:
C#
public class CompanyDetails
{
public string CompanyName
{
get;
set;
}
public string Location
{
get;
set;
}
public int EmployeeAge
{
get;
set;
}
public String EmloyeeFirstName
{
get;
set;
}
public string EmployeeLastName
{
get;
set;
}
}
VB.NET
Public Class CompanyDetails
Private privateCompanyName As String
Public Property CompanyName() As String
Get
Return privateCompanyName
End Get
Set(ByVal value As String)
privateCompanyName = value
End Set
End Property
Private privateLocation As String
Public Property Location() As String
Get
Return privateLocation
End Get
Set(ByVal value As String)
privateLocation = value
End Set
End Property
Private privateEmployeeAge As Integer
Public Property EmployeeAge() As Integer
Get
Return privateEmployeeAge
End Get
Set(ByVal value As Integer)
privateEmployeeAge = value
End Set
End Property
Private privateEmloyeeFirstName As String
Public Property EmloyeeFirstName() As String
Get
Return privateEmloyeeFirstName
End Get
Set(ByVal value As String)
privateEmloyeeFirstName = value
End Set
End Property
Private privateEmployeeLastName As String
Public Property EmployeeLastName() As String
Get
Return privateEmployeeLastName
End Get
Set(ByVal value As String)
privateEmployeeLastName = value
End Set
End Property
End Class
In our example, we will be grouping by CompanyName, Location and EmployeeAge.
Step 4: For grouping purpose we have to use PropertyGroupDescription property which is in System.ComponentModel assembly. Open MainPage.Xaml file and add a xmlNamespace reference to the assembly System.ComponentModel which is having PropertyGroupDescription property.
We will add xmlNamespace in usercontrol section of Xaml as shown below:
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="DataGridGrouping.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:group="clr-namespace:System.Windows.Data;assembly=System.ComponentModel"
Width="600" Height="400">
Step 5: Now add the DataGrid from the toolbox and specify properties in the GroupDescription Property of DataGrid, based on which you want to Group the data. In our case, we will be grouping by CompanyName, Location and EmployeeAge. Our .xaml File will look like this.
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="DataGridGrouping.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:group="clr-namespace:System.Windows.Data;assembly=System.ComponentModel"
Width="600" Height="400">
<Grid x:Name="LayoutRoot" Background="White">
<data:DataGrid x:Name="dgCompDetails" AutoGenerateColumns="True">
<data:DataGrid.GroupDescriptions>
<group:PropertyGroupDescription PropertyName="CompanyName" />
<group:PropertyGroupDescription PropertyName="Location" />
<group:PropertyGroupDescription PropertyName="EmployeeAge" />
data:DataGrid.GroupDescriptions>
data:DataGrid>
Grid>
UserControl>
As shown above, the propertygroupdescriptions have been created for CompanyName, Location and EmployeeAge.
Step 6: We will now create a list of CompanyDetails and bind it to DataGrid.
So our complete Codebehind file will look like this.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace DataGridGrouping
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
List<CompanyDetails> compDetails = new List<CompanyDetails>();
compDetails.Add(new CompanyDetails() { CompanyName = "Symphony Services",Location="Bangalore", EmployeeAge=23,EmloyeeFirstName="Harsh" ,EmployeeLastName="Bardhan"});
compDetails.Add(new CompanyDetails() { CompanyName = "Symphony Services",Location="Bangalore", EmployeeAge=23,EmloyeeFirstName="Ashish", EmployeeLastName="Kumar"});
compDetails.Add(new CompanyDetails() { CompanyName = "Symphony Services", Location = "Bangalore", EmployeeAge = 24, EmloyeeFirstName = "Nimesh", EmployeeLastName = "Prabhakar" });
compDetails.Add(new CompanyDetails() { CompanyName = "Symphony Services", Location = "Pune", EmployeeAge = 23, EmloyeeFirstName = "Selva", EmployeeLastName = "Mohandoss" });
compDetails.Add(new CompanyDetails() { CompanyName = "Symphony Services", Location = "Pune", EmployeeAge = 23, EmloyeeFirstName = "Raj", EmployeeLastName = "Kumar" });
compDetails.Add(new CompanyDetails() { CompanyName = "DotNet Curry", Location = "Pune", EmployeeAge = 30, EmloyeeFirstName = "Suprotim", EmployeeLastName = "Agarwal" });
compDetails.Add(new CompanyDetails() { CompanyName = "DotNet Curry", Location = "Pune", EmployeeAge = 32, EmloyeeFirstName = "Carol", EmployeeLastName = "Nadarwalla" });
dgCompDetails.ItemsSource=compDetails;
}
}
public class CompanyDetails
{
public string CompanyName
{
get;set;
}
public string Location
{
get;set;
}
public int EmployeeAge
{
get;set;
}
public String EmloyeeFirstName
{
get;set;
}
public string EmployeeLastName
{
get;set;
}
}
}
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Namespace DataGridGrouping
Partial Public Class MainPage
Inherits UserControl
Public Sub New()
InitializeComponent()
Dim compDetails As New List(Of CompanyDetails)()
compDetails.Add(New CompanyDetails() With {.CompanyName = "Symphony Services", .Location="Bangalore", .EmployeeAge=23, .EmloyeeFirstName="Harsh", .EmployeeLastName="Bardhan"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "Symphony Services", .Location="Bangalore", .EmployeeAge=23, .EmloyeeFirstName="Ashish", .EmployeeLastName="Kumar"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "Symphony Services", .Location = "Bangalore", .EmployeeAge = 24, .EmloyeeFirstName = "Nimesh", .EmployeeLastName = "Prabhakar"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "Symphony Services", .Location = "Pune", .EmployeeAge = 23, .EmloyeeFirstName = "Selva", .EmployeeLastName = "Mohandoss"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "Symphony Services", .Location = "Pune", .EmployeeAge = 23, .EmloyeeFirstName = "Raj", .EmployeeLastName = "Kumar"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "DotNet Curry", .Location = "Pune", .EmployeeAge = 30, .EmloyeeFirstName = "Suprotim", .EmployeeLastName = "Agarwal"})
compDetails.Add(New CompanyDetails() With {.CompanyName = "DotNet Curry", .Location = "Pune", .EmployeeAge = 32, .EmloyeeFirstName = "Carol", .EmployeeLastName = "Nadarwalla"})
dgCompDetails.ItemsSource=compDetails
End Sub
End Class
Public Class CompanyDetails
Private privateCompanyName As String
Public Property CompanyName() As String
Get
Return privateCompanyName
End Get
Set(ByVal value As String)
privateCompanyName = value
End Set
End Property
Private privateLocation As String
Public Property Location() As String
Get
Return privateLocation
End Get
Set(ByVal value As String)
privateLocation = value
End Set
End Property
Private privateEmployeeAge As Integer
Public Property EmployeeAge() As Integer
Get
Return privateEmployeeAge
End Get
Set(ByVal value As Integer)
privateEmployeeAge = value
End Set
End Property
Private privateEmloyeeFirstName As String
Public Property EmloyeeFirstName() As String
Get
Return privateEmloyeeFirstName
End Get
Set(ByVal value As String)
privateEmloyeeFirstName = value
End Set
End Property
Private privateEmployeeLastName As String
Public Property EmployeeLastName() As String
Get
Return privateEmployeeLastName
End Get
Set(ByVal value As String)
privateEmployeeLastName = value
End Set
End Property
End Class
End Namespace
Step 7: Run your application and you will find that items are grouped based on the specified GroupColumn (see Screenshot below).
Static Grouping
Well that was the first part of this article, where we explored how to bind and group data with static a datasource. What we will do now is connect the DataGrid to a database and then group data. I will use Linq to SqlClasses and WebServices (will keep that very simple).
Note: We can use RIAServices / WCF or ADOT DataServices also.
Note: I am assuming you have SQLServer installed and you have the Northwind database.
If you don’t have the Northwind database required for this example, you can download it from link mentioned below and run script. http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&displaylang=en
Step 8: Go to your WebProject DataGridGrouping.Web project and add LinqToSql classes and name it as Customers.dbml.
Add New item
Step 9: You will get Designer Page of the dbml file. Click on the Server Explorer and point to the ‘Northwind’ database by specifying your ServerName and credentials.
Select Customer Table of Northwind from Server Explorer and drag it to the designer surface of the dbml file.
Customer Table
Step 10: Set ‘SerializationMode’ property of CustomersDataContext to Unidirectional (see screenshot below) and click on Save.
Serialization
Step 11: Now we will add a webservice to our project. Go To your WebProject DataGridGrouping.Web Project > add a ‘Web Service’ and name it as ‘CustomerService.asmx’ > click on Add.
Add New Item
Step 12: Now modify the default ‘HelloWorld’ method and change its name to ‘CustomerDetails’ and the return type of that to List.
Your service class will look like this.
C#
namespace DataGridGrouping.Web
{
///
/// Summary description for EmployeeService
///
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class CustomerService : System.Web.Services.WebService
{
[WebMethod]
public List CustomerDetails()
{
//Creating CustomerContext object and returning customer list
CustomersDataContext customerContext = new CustomersDataContext();
return customerContext.Customers.ToList();
}
}
}
VB.NET
Namespace DataGridGrouping.Web
'''
''' Summary description for EmployeeService
'''
' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
' [System.Web.Script.Services.ScriptService]
Namespace := "http://tempuri.org/"), WebServiceBinding(ConformsTo := WsiProfiles.BasicProfile1_1), System.ComponentModel.ToolboxItem(False)> _
Public Class CustomerService
Inherits System.Web.Services.WebService
_
Public Function CustomerDetails() As List(Of Customer)
'Creating CustomerContext object and returning customer list
Dim customerContext As New CustomersDataContext()
Return customerContext.Customers.ToList()
End Function
End Class
End Namespace
Step 13: Now add a reference to your service in your Silverlight (“DataGridGrouping”) Project and set the namespace as ‘CustomerService’.
Add Service Reference
Step 14: Now open your Page.xaml and specify the ‘Country’ and ‘City’ as Grouping parameter since our datasource is having these property.
Our Page.Xaml will look like this.
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="DataGridGrouping.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:group="clr-namespace:System.Windows.Data;assembly=System.ComponentModel"
Width="600" Height="400">
<Grid x:Name="LayoutRoot" Background="White">
<data:DataGrid x:Name="dgCompDetails" AutoGenerateColumns="True">
<data:DataGrid.GroupDescriptions>
<group:PropertyGroupDescription PropertyName="Country" />
<group:PropertyGroupDescription PropertyName="City" />
data:DataGrid.GroupDescriptions>
data:DataGrid>
Grid>
UserControl>
Step 15: Now call the service method and in its completed handler, set DataGrid’s ItemSource. Our Page will look like this.
C#
namespace DataGridGrouping
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
CustomerService.CustomerServiceSoapClient customerClient =
new CustomerService.CustomerServiceSoapClient();
customerClient.CustomerDetailsAsync();
customerClient.CustomerDetailsCompleted +=
new EventHandler(customerClient_CustomerDetailsCompleted);
}
void customerClient_CustomerDetailsCompleted(object sender, DataGridGrouping.CustomerService.CustomerDetailsCompletedEventArgs e)
{
dgCompDetails.ItemsSource = e.Result;
}
}
}
VB.NET
Namespace DataGridGrouping
Partial Public Class MainPage
Inherits UserControl
Public Sub New()
InitializeComponent()
Dim customerClient As New CustomerService.CustomerServiceSoapClient()
customerClient.CustomerDetailsAsync()
AddHandler customerClient.CustomerDetailsCompleted, AddressOf customerClient_CustomerDetailsCompleted
End Sub
Private Sub customerClient_CustomerDetailsCompleted(ByVal sender As Object, ByVal e As DataGridGrouping.CustomerService.CustomerDetailsCompletedEventArgs)
dgCompDetails.ItemsSource = e.Result
End Sub
End Class
End Namespace
Step 16: Now we are ready to run our application. Run your application and you will get the data grouped in the DataGrid as shown in the screen below
Running Application

No comments:

Popular Posts