New Feature Spotlight: Silverlight DataGrid
Applies To:
DataGrid for Silverlight
Author:
Suelinda Webster
Published On:
4/7/2009
ComponentOne DataGrid for Silverlight is even better for 2009 with three new features to enhance your data visualization applications. Now you can easily add Microsoft Outlook-style grouping, DateTime Columns, and Column Filtering to your Silverlight project. This article shows how easy it is to create a fully interactive grid. It walks you through the steps from creating a project, to creating the UI, to adding a database and Web service, and finally interacting with the grid at run time.
Step 1: Create a Silverlight Project
Open Microsoft Visual Studio 2008, and select "File | New | Project" from the main menu.
Select Visual C# as your language, and then select the "Silverlight Application" project type. Let's call the project "ComponentOneDataGrid", so enter that as the project name and click the OK button.
The Add Silverlight Application dialog box will appear.
Please make sure that the "Add a new ASP.NET Web project to the solution to host Silverlight" radio button is selected, and that "ASP.NET Web Application Project" is selected as the Project Type. The name ComponentOneDataGrid.Web will have been filled in for you, so click the OK button to continue.
Step 2: Create the User Interface
If Visual Studio does not open Page.xaml for you by default, go to the ComponentOneDataGrid project in the Project explorer and double-click on the Page.xaml file in the list.
Notice the split view with the design view (above) and XAML view (below). Go to the XAML view and find the following portion of the UserControl tag, which defines the Width and Height of the Silverlight application:
Width="400" Height="300">
We will need a little more room than this, so change the Width to 600 and the Height to 400. The entire UserControl start tag should now look like this:
<UserControl x:Class="ComponentOneDataGrid.Page"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="600" Height="400">
Next go to the XAML view and find the following line:
This is where we will start defining the layout of the Silverlight application by adding some rows to the layout grid. We will need 6 rows in all to hold a title for our application, some detail, and the ComponentOne DataGrid for Silverlight.
Let's add the following rows, directly under the line you just found:
Now, to fill the layout grid rows, add a title to the top row of the layout grid by inserting the following XAML immediately after the code above:
The next three rows of the layout grid will show the new features that this tutorial demonstrates: Microsoft Outlook-style grouping, DateTime Column, and Filtering.
Now we can add the ComponentOne DataGrid for Silverlight to the layout. The easiest way to add the control is to select the **C1DataGrid** from the toolbox, which is listed under the "Silverlight XAML Controls" tab, and drag the cursor below the code you added above. This will add the necessary ComponentOne Silverlight references, C1.Silverlight and C1.Silverlight.Datagrid.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/4_C1References.bmp)
In addition to the references, two lines of code will also be added to the XAML. The following code will be added to the top of the XAML:
xmlns:c1grid="clr-namespace:C1.Silverlight.DataGrid;assembly=C1.Silverlight.DataGrid"
The second line of code will appear at the position where you dragged the **C1DataGrid**.
This last line of code is what we are going to work with now. Notice that the grid has been added to the form, but it is not at the position that we want it, which is right below the text we added previously. We just need to add a little more information to the **C1DataGrid** start tag.
Let's name the C1DataGrid "_C1DataGrid". To position the grid below the text we also need to add positioning information to the tag, so add to the line of code that was generated for us. It should look like this:
There is one more row in the layout grid, which will be used to display status information text. Add the following code below the grid:
The basic layout is now complete, and will look like this:
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/5_LayoutView.bmp)
Now we can implement the server side, and ultimately bind the **C1DataGrid** to a datasource so we can see the new features.
### Step 3: Add a Database
We need to add data to our application, so go to the ComponentOneDataGrid.Web project in the Solution Explorer, and add the NorthWind database to it by right-clicking the App_Data node and selecting "Add | Existing Item." from the context menu. The **Add Existing Item** dialog box will appear.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/6_addexistingitem.bmp)
From the dialog box browse to NWIND.MDB (located in the **C:\\Program Files\\ComponentOne\\Studio for Silverlight\\Samples\\C1\_MDSL\\C1\_MDSLWeb\\App_Data** directory by default), select it, and click the **Add** button to add the file to your project.
Next, select NWIND.MDB in the Solution Explorer to display its properties in the Properties window.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/7_database.bmp)
Set the **Build Action** property to **None**.
### Step 4: Add a Web Service
Now we need some code to transfer data to and from the database, so we are going to use the existing SmartDataSet.cs for convenience. It is part of the ControlExplorer sample that ships with ComponentOne Studio for Silverlight.
To add SmartDataSet.cs to the ComponentOneDataGrid.Web project, right-click the project and select "Add | Existing Item." from the context menu.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/8_addexistingitem2.bmp)
Browse to the SmartDataSet.cs file from the **Add Existing Item** dialog box, and click the **Add** button. The file is installed to **C:\\Program Files\\ComponentOne\\Studio for Silverlight\\Samples\\C1\_MDSL\\C1\_MDSLWeb\\SmartDataSet.cs** by default.
Next, we need to add a Web Service so we can get the data to the client. To add the Web Service, right-click on the ComponentOneDataGrid.Web project and go to "Add | New Item." to get the **Add New Item** dialog box.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/9_addnewitem.bmp)
Select the Web node from the left pane, and then select the "Web Service" item from the right pane. Name the Web Service "DataService.asmx" and click the **Add** button.
After you click the **Add** button, the new DataService.asmx file will be opened for you. We need to add some code to this Web Service. Begin by adding the following using directives to the top of the file:
using System.IO;
using System.Data;
using C1_MDSLWeb; //SmartDataSet namespace
Next, uncomment the [System.Web.Script.Services.ScriptService] line:
[System.Web.Script.Services.ScriptService]
Now, delete the HelloWorld method and add the following code to grab the data from the database:
[WebMethod]
public byte[] GetData(string tables)
{
// Create DataSet with connection string
var ds = GetDataSet();
// Load data into DataSet
ds.Fill(tables.Split(','));
// Persist to stream
var ms = new System.IO.MemoryStream();
ds.WriteXml(ms, XmlWriteMode.WriteSchema);
// Return stream data
return ms.ToArray();
}
SmartDataSet GetDataSet()
{
// Get physical location of the mdb file
string mdb = Path.Combine(
Context.Request.PhysicalApplicationPath, @"App_Data\nwind.mdb");
// Check that the file exists
if (!File.Exists(mdb))
{
string msg = string.Format("Cannot find database file {0}.", mdb);
throw new FileNotFoundException(msg);
}
// Make sure file is not read-only (source control often does this...)
FileAttributes att = File.GetAttributes(mdb);
if ((att & FileAttributes.ReadOnly) != 0)
{
att &= ~FileAttributes.ReadOnly;
File.SetAttributes(mdb, att);
}
// Create and initialize the SmartDataSet
var dataSet = new SmartDataSet();
dataSet.ConnectionString =
"provider=microsoft.jet.oledb.4.0;data source=" mdb;
return dataSet;
}
We are now finished with the ComponentOneDataGrid.Web project. Right-click on the project and select **Build** from the context menu before moving on to Step 5.
### Step 5: Use the Web Service
Go back to the ComponentOneDataGrid project, and right-click the References node. Select "Add Service Reference" from the context menu.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/10_addservicereference.bmp)
From the **Add Service Reference** dialog box, click the **Discover** button, and it will find the DataService.asmx automatically. There will be an automatically generated Namespace, but change it to "DataService" instead and click the **OK** button.
Now go to the Solution Explorer and expand the Page.xaml node. Double-click Page.xaml.cs to open it.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/11_CScodebehind.bmp)
Start by adding the following using directives:
using System.IO;
using C1.Silverlight.Data;
using ComponentOneDataGrid.DataService;
Then add to the page constructor so that it looks like this:
public Page()
{
InitializeComponent();
LoadData();
}
Now implement the LoadData and svc_GetDataCompleted methods to get the data from the Web Service:
DataSet _ds = null;
void LoadData()
{
// Invoke Web service
var svc = GetDataService();
svc.GetDataCompleted = svc_GetDataCompleted;
//svc.GetDataAsync("Categories,Products,Employees");
svc.GetDataAsync("Employees");
}
void svc_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
// Handle errors
if (e.Error != null)
{
_tbStatus.Text = "Error downloading data...";
return;
}
// Parse data stream from server (DataSet as XML)
_tbStatus.Text = string.Format(
"Got data, {0:n0} kBytes", e.Result.Length / 1024);
var ms = new MemoryStream(e.Result);
_ds = new DataSet();
_ds.ReadXml(ms);
// Got the data, bind controls to it
BindData();
}
Next, implement the GetDataService() method:
// Get data service relative to current host/domain
DataServiceSoapClient GetDataService()
{
// Increase buffer size
var binding = new System.ServiceModel.BasicHttpBinding();
binding.MaxReceivedMessageSize = 2147483647; // int.MaxValue
binding.MaxBufferSize = 2147483647; // int.MaxValue
// get absolute service addres
Uri uri = C1.Silverlight.Extensions.GetAbsoluteUri("DataService.asmx");
var address = new System.ServiceModel.EndpointAddress(uri);
// Return new service client
return new DataServiceSoapClient(binding, address);
}
Finally, implement BindData():
void BindData()
{
// get the tables
DataTable dtEmployees = _ds.Tables["Employees"];
// populate categories grid
_c1DataGrid.ItemsSource = dtEmployees.DefaultView;
}
We are now finished with the Page.xaml.cs code, so you can right-click the ComponentOneDataGrid solution and select **Rebuild Solution** from the context menu.
### Step 6: Experimenting with the New Features
Click the green arrow icon from the Visual Studio toolbar to run the application in debug mode.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/12_debug.bmp)
The grid loads with default behavior.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/13_DefaultBehavior.bmp)
Notice that the Outlook-Style Grouping does not happen by default, but you can already see that the DateTime column is added automatically. Since the BirthDate field did not specify a time, the time defaults to 12:00.
If you mouse-over any of the column headers, you will see a little arrow appear to the right of the header. If you click the header, you will get a dropdown form with filtering options. Let's mouse-over the Title column, and click the filter dropdown arrow.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/14_filter2.bmp)
This is the filter that appears for standard text. You get a dropdown that can either have a value of "Contains" or "Starts With", and a text box where you can add text to filter. Either leave "Contains" selected or select "Starts With", then type "Rep" in the text field and click the **Filter** button. This will display all of the Sales Representatives. If you no longer want the filter, you can open the filter dialog again and click the **Clear** button.
Numeric columns give you filtering options suited to numbers. For example, mouse-over the EmployeeID column, and click the filter dropdown arrow to the right. The filter options look like this:
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/15_numberfilter.bmp)
The DateTime column's filter looks like this:
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/16_datefilter.bmp)
You can choose a start date and time, and an end date and time to filter.
Now that we know which new features are available by default, close the Silverlight application and return to Visual Studio. Open Page.xaml, and find the following line of code:
Let's allow the Outlook-style Grouping by adding the CanUserGroup attribute to the c1grid tag, and setting it to true.
Now, right-click the solution and select **Rebuild Solution** from the context menu. Click the green arrow icon from the Visual Studio toolbar to run the application in debug mode.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/17_group2.bmp)
Notice the drag area at the top of the C1DataGrid. Just drag any column header on top of that area to group on that column. You can even group on more than one column. For example, try dragging and dropping the "TitleOfCourtesy" and "Title" columns into the area.
![](//cdn.mescius.io/assets/developer/blogs/legacy/c1/2009/4/18_multigroup.bmp)
The columns will group in the order you dropped them.
ComponentOne DataGrid for Silverlight makes it easy to create a fully interactive grid with Outlook-style grouping, DateTime columns, and filtering. Other key features of DataGrid for Silverlight include: cell editing, row merging, image displays in cells, ability to add/remove rows, and more.
[Download Studio for Silverlight.](https://www.componentone.com/SuperProducts/StudioSilverlight/)