Click here to Skip to main content
Click here to Skip to main content

Sorting XML Data using the .NET DataGrid

, 7 Feb 2002
Rate this:
Please Sign up or sign in to vote.
Sorting different data types of XML Data in a DataGrid
<!-- Download Links --> <!-- Article image -->

Sample Image - XMLDataGrid.jpg

<!-- Add the rest of your HTML here -->

Introduction

Displaying data from various datasources like Database, XML etc. has never been easier since the advent of ASP.NET's Server Control DataGrid. The DataGrid control is used to display data from the datasource defined by its DataSource property. There are tonnes of features provided by DataGrid in displaying data. Sorting each column when clicked on the name of the column in the DataGrid is one of the best features. We will concentrate on sorting XML.

Displaying XML data using DataGrid and achieving the same tasks is a little bit different. The reason is, as such an XML file when loaded by a DataGrid will only display the XML content as "text". On the other hand, data from a database table will have all the constraints (like what type of data - int, float, double,...) embedded into the DataGrid instance. So you dont have to emphasize in your code that "Col1 of my data is of type integer(and not text)".

But if you display XML you have to specify somehow or other that what type of data each of your column contains. Otherwise, all values are considered as type "text". Remember, you have to do this only if you want to get certain type-specific features of DataGrid. If you dont need these features, but simply want to display your XML in a DataGrid you dont have to worry at all. You can proceed in the same way as you do for displaying your SQL data.

Assumptions

Before I proceed I assume my readers are familiar with the following. Please do not worry if you dont know any of the listed. You may still proceed as I have made the article so simple and not added complex issues.

  • XML and Schemas
  • ASP.NET code-behind files
  • Basic HTML Authoring

Contents

This article is broken down into pieces of subsections named as follows. This will walk you through the entire steps to do Sorting of XML data.

  • DataGrid and properties - Design time and Run time
  • AllowSorting property and OnSortCommand method
  • The BindGrid function
  • Sample XML and XSD files explained

There are two sample files that I have included in this article. XMLDataGrid.ASPX (the template file) and XMLData.CS (the code-behind file). My data files are books.XML and books.XSD. Down the road we will learn how to design all the sample files. Lets get ourselves wet.

DataGrid and properties

First lets see how to write our XMLDataGrid.ASPX file. This file acts like a template to generate the DataGrid table. Attaching the data (technically called DataBinding) to the grid and assigning other properties are done in the code behind file. To add a DataGrid to an ASP.NET web form we use the <asp:DataGrid> tag. So we add the following code to our ASPX page which already contains the <html> tags.

<body>
<form runat="server">
    <span class="normaltext">Find the difference between sorting of 
     Item Id column and Amount column</span>
    <br>
    <asp:datagrid runat="server">
    </asp:datagrid>
</form>
</body>

A point to ponder:- Note in the file the Page attribute has Inherits property set to our class name (XMLDataMain) in our code-behind file and Src property set to .CS file.

AllowSorting property and OnSortCommand method

Following are the design time properties that we are setting for our DataGrid control in our ASPX file.

CssClass=asptable
id="XMLDataGrid"
CellSpacing="1"
OnSortCommand="SortGrid"
AllowSorting="True"

The CssClass property allows you to set any custom styles you want to apply to the grid. The id property is the unique identifier for our DataGrid control. This identifier is used in our code-behind file to handle our DataGrid programmatically. The OnSortCommand is used to specify our custom function that should be called when the column names of the DataGrid is clicked. This will work only when the AllowSorting property is set to "true". If the AllowSorting property is true you will automatically get hyperlinks to your column names. Easy, isnt it!! when you hear something is done AUTOMATICALLY. This is pretty much it for our .ASPX file. Now lets move on to our code-behind file. The XMLData.CS.

The BindGrid function

To better understand our code-behind file, lets discuss what do we need to do further to achieve our goal. We have our DataGrid ready to receive any data and its also ready to sort the columns based on the implementation of SortGrid function. So all we need is a function which binds the XML data with the DataGrid. Also we are making it so general that our SortGrid function is going to make use of that function and just tells what column needs to be sorted. Of course, Sorting is binding same data to the Grid but the rows are shuffled based on our Sort field.

Lets call our function as BindGrid(). Now BindGrid has to read the XML and bind it to the DataGrid. The following code snippet would simply do this.

using System;
using System.XML;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

public class XMLDataMain : Page
{
    public DataGrid XMLDataGrid;
    
    protected void Page_Load(Object src, EventArgs e)
    {
        if(!IsPostBack)
        {
            BindGrid();
        }
    }
    
    protected void BindGrid()
    {
        string dataUrl = "books.XML";
        
        DataSet ds = new DataSet();
        ds.ReadXML(Server.MapPath(dataUrl));
        
        DataView dv = new DataView(ds.Tables[0]);
        
        XMLDataGrid.DataSource = dv;
        XMLDataGrid.DataBind();
    }
}

A point to ponder:- Refer MSDN documentation for more details on DataBinding. I have used Server.MapPath() function. So, for the demo code to work, you should unzip all the files under the same folder. Or if you want to copy the XML data file to a different folder, please change the argument of the ReadXML() in the above code.

The ReadXML method of the DataSet class understands the specified XML data and converts it into a relational format (meaning, tables, columns, rows, constraints etc.). Then a DataView is created using the first and only table in the DataSet ds. This view becomes our DataSource and once we call the DataBind function of our grid, the XML data is rendered in a table format. So we call our BindGrid function from Page_Load. But we are not completed yet.

Sorting the columns

We are going to use a special state management feature ViewState provided by ASP.NET to achieve our sorting. We can achieve it in a much simpler way, but this will also help you to learn this cool new feature. For more information on ViewState refer to Taking a Bite Out of ASP.NET ViewState. We are going to use two custom-defined properties to handle our Sorting. They are

  • SortField, name of the field which should be sorted on a particular request.
  • SortAscending, a boolean value to toggle our sorting between Ascending and Descending when the user clicks the same column many times.

Add the following code to our XMLDataMain class

// using ViewState for SortField property
// For more information about using ViewState bags read <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp11222001.asp">this</a> reference
    string SortField {

        get {
            object o = ViewState["SortField"];
            if (o == null) {
                return String.Empty;
            }
            return (string)o;
        }

        set {
            if (value == SortField) {
                //if ascending change to descending or vice versa.
                SortAscending = !SortAscending;
            }
            ViewState["SortField"] = value;
        }
    }

    // using ViewState for SortAscending property
    bool SortAscending {

        get {
            object o = ViewState["SortAscending"];
            if (o == null) {
                return true;
            }
            return (bool)o;
        }

        set {
            ViewState["SortAscending"] = value;
        }
    }

The only complication that you find in these get/set methods are the usage of ViewState (if you were not aware of it before). If its too much to understand, in order to proceed with the article, just think of the way you assign a Session variable in traditional ASP. ViewState is something like that. I dont want to get too much into ViewState functionality. For more details, refer to the above specified link. Also, Note that we toggle the SortAscending property, if its true then sort by Ascending order otherwise by Descending.

Lets go back to our BindGrid function and make certain changes to handle sorting. We already know that BindGrid is the only function we rely one, for any rendering changes. So here are our changes.

protected void BindGrid()
{
    string dataUrl = "books.XML";
    
    DataSet ds = new DataSet();
    ds.ReadXML(Server.MapPath(dataUrl));
    
    DataView dv = new DataView(ds.Tables[0]);
    DataTable dt = dv.Table;
    
    //Sorting criteria
    dv.Sort = SortField;
    if (!SortAscending)
    {
        // append "DESC" to the sort field name in order to 
        // sort descending
        dv.Sort += " DESC";    
    }
        
    XMLDataGrid.DataSource = dv;
    XMLDataGrid.DataBind();
}

We use the Sort property of the DataView and specify which field needs to be sorted. We also append the string Desc with the field name if we want descending order sorting. By default a column will be sorted in the ascending order. We are almost there. Now the only final thing that we have to finish is to hook up this function to our SortGrid command function. Because this is the function which will be called when the user requests Sorting of a column by clicking the column name.

Guess what we have to write in our SortGrid command function?? Change the SortField property to which the user requested and call the BindGrid function and you are all set. Here is the code.

protected void SortGrid(Object src, DataGridSortCommandEventArgs e)
{
    XMLDataGrid.CurrentPageIndex = 0;
    // get the requested sorting field name and set it to SortField
    SortField = e.SortExpression;    
    BindGrid();
}

Since we would be having only one page to display we set the pageindex to 0. If you have custom Paging feature enabled you set the appropriate page index to sort. Then we set our SortField property to the one the user requested. The user requested field name is stored in the DataGridSortCommandEventArgs object's SortExpression property. Finally we call our BindGrid() function.

Sorting Integers - Sample XML and XSD files

So far everything will work fine. But if you try to click on the columns (<iid> and <iamount>) where numbers appear the sorting behaves differently. Kinda disappointing. The numbers are sorted as if they are text. So 8 becomes > 120. This is not what we want from our DataGrid. The only way is to tell the DataGrid that the XML tags which bears numbers are real numbers and not text. To do this we define our own Schema and load the schema along with our XML into the DataGrid.

So lucky we are, that we have this ReadXMLSchema method in DataSet class, to load our Schema and validate our XML against this Schema. This will also caution the DataSet while preparing the relational information of whatever data that is loaded. If it is loaded with an XML data it checks whether a Schema is loaded along with that. If so it uses the schema to analyze the XML data and prepares itself based on what is said in the Schema about the XML. If you see the sample Schema (books.XSD) you may notice that

<ElementType name="iid" content="textOnly" dt:type="ui4"/>

The iid element is defined as unsigned integer. I have also deliberately left the iamount element as string to find the difference between sorting of two number columns. Here is the code change that the BindGrid needs to undergo.

protected void BindGrid()
{
    string dataUrl = "books.XML";
    string schemaUrl = "books.XSD";
    
    DataSet ds = new DataSet();
    ds.ReadXMLSchema(Server.MapPath(schemaUrl));
    ds.ReadXML(Server.MapPath(dataUrl));
    
    DataView dv = new DataView(ds.Tables[0]);
    DataTable dt = dv.Table;
    
    //Custom names for the columns
    dt.Columns[0].ColumnName = "Item Description";
    dt.Columns[1].ColumnName = "Item Id";
    dt.Columns[2].ColumnName = "Amount";
    
    //Sorting criteria
    dv.Sort = SortField;
    if (!SortAscending)
    {
        // append "DESC" to the sort field name in order to 
        // sort descending
        dv.Sort += " DESC";    
    }
       
    XMLDataGrid.DataSource = dv;
    XMLDataGrid.DataBind();
}

A point to ponder:- You should call the ReadXMLSchema method before you call ReadXML method.

Didnt you find any difference in the snippet that I added just above. Anything new!! Anything interesting!! Here it is. Since the DataSet reads the XML it also gives column names as it was found in the original data. I dont like it nor do you, I guess. I dont want to change my XML tag names just for the sake of it. So I changed the column names by using the ColumnName property of each column in the DataTable.

Conclusion

There are a lot of interesting properties and methods in the DataGrid class, like editing the XML data from the grid and saving them back and many more. Explore them per your wish and enjoy .NETing!!!

References

Fun exercises

Wanna mess with our DataGrid and find out whatelse can it do? Try these.

  • Convert the iamount tag into a float datatype and try to display it in the form US$... Now try to sort it. You should sort only the amount not the entire string US$...
  • Find out how sorting works if you have case sensitive strings
  • Change one of the iid to a string like, abc or something and see how its rendered. Try to handle the exception if you get any...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

omkamal
Web Developer
United States United States
Started programming with computers in 1995. Ever since it keeps me busy and creative. Did a bachelor's degree in electronics and communication only to better understand the inside of computers and its power. Currently working as a software developer in US and looking for a girl-friend...

Comments and Discussions

 
GeneralThanks! PinmemberSpike Himself13-Aug-09 23:12 
GeneralSelect Data PinmemberPaul R Morrison25-May-08 11:43 
GeneralCostum Sort Pinmemberjudith1236-Mar-05 21:01 
Generallayered XML Pinmemberjudith12315-Feb-05 21:35 
GeneralRe: layered XML PinmemberDrMayo19-Feb-05 2:46 
GeneralDefault Sort Pinmembersonystyle14-Oct-04 9:50 
GeneralVery Very Nice PinsussSebCode5-Oct-04 14:50 
GeneralRe: Very Very Nice Pinmembererax dan13-Aug-08 22:23 
Generalwin form datagrid PinmemberPradeep K V7-Sep-04 2:53 
GeneralSorting PinmemberAppelz26-Apr-04 4:21 
QuestionJapanese font in xml data ? Pinmembergeoneoration28-Jan-03 18:47 
GeneralHelp PinmemberChagit17-Sep-02 23:38 
GeneralXml Quik Buider Pinmembershak30-Jun-02 19:44 
GeneralRe: Xml Quik Buider PinmemberChristian Graus30-Jun-02 20:11 
GeneralRe: Xml Quik Buider Pinmembershak1-Jul-02 4:55 
GeneralYes! It is a very good Article PinmemberPooran11-Feb-02 3:17 
GeneralUpdation of the article Pinmemberomkamal8-Feb-02 9:27 
GeneralRe: Updation of the article PinmemberJames T. Johnson9-Feb-02 21:16 
GeneralNice one PinmemberPaul Watson6-Feb-02 22:03 
GeneralRe: Nice one Pinmemberomkamal7-Feb-02 4:03 
GeneralRe: Nice one PinmemberPaul Watson7-Feb-02 4:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140814.1 | Last Updated 8 Feb 2002
Article Copyright 2002 by omkamal
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid