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

An ASP.NET DataGrid with AutoFilter

By , 13 May 2006
 

Sample Image - DataGridAF1.gif

Introduction

In this article I will show a new web control, a DataGrid with a HtmlSelect control in each column which allows a filter selection of items, like Microsoft Excel AutoFilter does. The control is directly inherited from System.Web.UI.WebControls.DataGrid and was tested under Microsoft IE 6.0, Mozilla FireFox 1.0.2, Netscape 7.2, Opera 7.54.

Using the code

Add the DataGridAF.dll to your project’s references and toolbox, and use it as a DataGrid base control. The only difference is a new property, ShowFilter, which allows you to show or hide the HtmlSelect controls in the columns header.

To run the demo project, unzip it under a virtual directory and start it. In the demo project, DataGridAF data are loaded from a xml file, Customers.xml (a select from Customers in Northwind database), so you don’t need to connect to a database.

The DataGridAutoFilter Class

DataGridAutoFilter class is very easy. All we need is to override two methods: OnItemDataBound and RaisePostBackEvent. The first is raised after each item is data bound to the DataGrid control and is where HtmlSelect controls are loaded (thank to Tony Truong's article for the idea); the second is used to capture the post back event raised when a HtmlSelect element is selected and is inherited from the IPostBackEventHandler interface (see this David S. Platt's book for a complete description).

OnItemDataBound Method

In this method all DataGrid items are data bound. First ListItemType.Header, then ListItemType.Item, ..., last ListItemType.Footer.

override protected void OnItemDataBound(DataGridItemEventArgs e)
{
    switch (e.Item.ItemType)
    {
        case ListItemType.Header:
            // see later on
            break;
        
        case ListItemType.Item:
        case ListItemType.AlternatingItem:
        case ListItemType.SelectedItem:
            // see later on
            break;

        case ListItemType.Footer:
            // see later on
            break;
    }
    
    base.OnItemDataBound(e);
}        

First Header: here is where the HtmlSelect is created, with “onchange” handler that causes a postback, it is added to an ArrayList to be accessed later on and it is added to the column header cell to be rendered. Also a SortedList object is created, but only to sort data before load in HtmlSelect.

case ListItemType.Header:
    for(int i=0; i< e.Item.Cells.Count; i++)
    {
        // ...
        
        // add a select element, with "onchange" handler that causes a postback to RaisePostBackEvent;
        HtmlSelect select = new HtmlSelect();
        select.Attributes.Add("onchange", Page.GetPostBackEventReference(this));
        e.Item.Cells[i].Controls.Add(select);
        // add the select element to the ArrayList;
        list.Add(select);
        
        // add a SortedList object, with an empty item;
        SortedList sorted = new SortedList();
        sorted.Add("", "");
        // load the SortedList object into the ArrayList;
        sort.Add(sorted);
    }
    break;

Then items are data bound: here SortedList are loaded with “distinct” values of the columns.

case ListItemType.Item:
case ListItemType.AlternatingItem:
case ListItemType.SelectedItem:
    for(int i=0; i< e.Item.Cells.Count; i++)
    {
        // fill the SortedList object with the "distinct" values from each columns;
        SortedList sorted = (SortedList)sort[i];
        if (sorted.ContainsValue(e.Item.Cells[i].Text) == false)
            sorted.Add(e.Item.Cells[i].Text, e.Item.Cells[i].Text);
    }
    break;

Last the footer: here the sorted data are copied from the SortedList objects to the HtmlSelect controls.

case ListItemType.Footer:
    for(int i=0; i< e.Item.Cells.Count; i++)
    {
        SortedList sorted = (SortedList)sort[i];
        HtmlSelect select = (HtmlSelect)list[i];
        // load sorted item into select element;
        for(int j=0; j< sorted.Count; j++)
            select.Items.Add(sorted.GetByIndex(j).ToString());
        sorted.Clear();
    }
    sort.Clear();
    break;

RaisePostBackEvent Method

Here is were each DataGrid item is shown or hidden, according to the user selections.

public void RaisePostBackEvent(string eventArgument)
{
    // for each row;
    for (int i=0; i< Items.Count; i++)
    {
        // for each column;
        for (int j=0; j< Items[i].Cells.Count; j++)
        {
            HtmlSelect select = (HtmlSelect)list[j];
            if (select.SelectedIndex > 0)
            {
                // hide rows with a not selected value;
                if (Items[i].Cells[j].Text != select.Items[select.SelectedIndex].Text)
                    Items[i].Visible = false;
            }
        }
    }
}

Conclusion

When you have many rows in a DataGrid and you wish to select a subset of data, an AutoFilter feature may be a solution. I have not found such a control on the web, so I tried to create it. DataGridAF is not a sophisticated control, and does not allow advanced selections like Excel AutoFilter does, but it is easy to use and you can also do multiple selections, wich can be combined with sorting or paging data.

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

About the Author

stefano piuri
Web Developer
Italy Italy
Member
I work for an Italian bank. I have 15+ years experience in bank and financial software.
I am interested in .NET (C#, ASP.NET, ...) and in SQL Server (TSQL, OLAP, ...) tecnologies.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: A little help?memberstefano piuri31 Mar '09 - 21:27 
The problem, You know, is not how modify the method “OnItemDataBound” where You can set “select.Visible = false” for some HtmlSelect elements, or do not create it at all.
 
You could:
- or create a new public property where store which columns can be filtered (but you have to manage it)
- or use a “e.Item” property to pass this information to the “OnItemDataBound” method (but which property ?)
- or add a new particular row where store the information (but you have to hide it – for example when you create it “DataGridAutoFilter1.Items[0].Visible = false” or you have to remove it before “base.OnItemDataBound(e)” in OnItemDataBound method is called
 
What do You think about it ?
Please, let me know how You will solve the problem.
 
Best regards.
stefano
GeneralRe: A little help?memberliferiders29 Oct '10 - 5:01 
Hello Stefano,
 
I am looking to incorporate an autoflter on my asp page, and I am hoping your solution would just be what I am looking for. However, I was not able to use your solution inspite of downloading the source file and the demo. Can you please answer the following questions.?
a) Do I need any special software installed to use your solution? If yes, what software?
b) After downloading the files, is there a step by step instruction list which I could follow, until I see this filter in action?
c) Finally, where can I find the entire source code?
 
Thank you for your immense help in advance. I have already wasted a week on finding a solution. Please help. Thanks.
GeneralNeed to turn autofiltering off in some columnsmemberlsantos200013 Jul '08 - 5:08 
Looks OK to me, thanks. Is there any any way to disable the comboxbox in a certain column?.. I don;t want to displya it in column 1 and 2
Questionsorting resets the filtering and clears all the drop downsmemberHermit Dave27 May '08 - 22:12 
Hi,
 
I am trying to consume this datagrid and i have noticed that filtering by itself works great. thanks for the custom datagrid. if i enabled sorting and add client side code to enable sorting and then i use sorting after setting a filter, the filter gets reset and the dropdowns clear.
 
I think it might have something to do with viewstate though i am still trying to figure the problem out. Any pointers would be appreciated
 
Regards,
 
Hermit
 
Regards,
 
Hermit Dave

General[Message Deleted]memberryuxuyr17 Apr '08 - 6:23 

GeneralRe: ComboBox updatememberstefano piuri18 Apr '08 - 3:15 
Thanks.
 
I think you can do it in RaisePostBackEvent, where you can hide or delete combobox's items.
Bye.
 
stefano piuri
Generalupdate to 2.0 pleasememberdamphire10 Jan '08 - 7:47 
Can you update your proyect to asp .net 2.0? i'm getting the same error posted below.
GeneralRe: update to 2.0 pleasememberstefano piuri11 Jan '08 - 2:22 
Hi.
 
DataGridAF.dll works with ASP.NET 1.1 and 2.0.
 
You can use DataGridAF.dll, compiled with .NET 1.1, in ASP.NET 2.0 projects.
Or You can compile DataGridAF.dll with 2.0 and use with ASP.NET projects.
 
Bye.
stefano
GeneralRe: update to 2.0 pleasemembercouter10 Mar '08 - 2:10 
Can I modify this component for System.Windows.Forms? How?
GeneralRe: update to 2.0 pleasememberstefano piuri12 Mar '08 - 4:17 
I think so, but using System.Windows controls.
You have to manage the event fired by the combo control and hide or show the items according the selection.
 
Best regards.
stefano
General[Message Deleted]memberVirtualRichard31 Oct '07 - 5:47 

GeneralRe: ASP.NET 2.0?memberstefano piuri31 Oct '07 - 6:52 
Hi.
 
DataGridAF.dll works with ASP.NET 1.1 and 2.0.
 
You can use DataGridAF.dll, compiled with .NET 1.1, in ASP.NET 2.0 projects.
Or You can compile DataGridAF.dll with 2.0 and use with ASP.NET projects.
 
Bye.
stefano

General[Message Deleted]memberVirtualRichard31 Oct '07 - 7:57 

GeneralRe: ASP.NET 2.0?memberSchnozToiger13 Mar '09 - 6:06 
Hi,
 
I want to use this component in my VS2008 ASP.Net 2.0 app but get the same error you mentioned. I was just wondering if you ever managed to get it sorted out?
 
Regards
AJ.
GeneralRe: ASP.NET 2.0?memberstefano piuri16 Mar '09 - 3:02 
It works with VS2003 but not always with VS2005 and more.
I think it is due to a different sequence of events between .net 1.1 and 2.0, where view state are loaded in some different ways.
I would like to rewrite the code, but now I am too busy in other works.
 
Regards.
stefano
GeneralThank for the examplememberntgrvt20 Feb '07 - 12:22 
This works just fine for my needs.
GeneralRe: Thank for the examplememberstefano piuri20 Feb '07 - 20:49 
Thank you.
stefano

QuestionError !?memberttphp24 May '06 - 21:53 
I have code:

private void Button1_Click(object sender, System.EventArgs e)
{
string fileName = System.AppDomain.CurrentDomain.BaseDirectory + "/Customers.xml";

DataSet1 = new DataSet();
DataSet1.ReadXml(fileName, XmlReadMode.ReadSchema);

DataGridAutoFilter1.DataSource = DataSet1;
DataGridAutoFilter1.DataMember = "Customers";
DataGridAutoFilter1.DataBind();
}

When I select colunm header then Error:
 

Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
 
Exception Details: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
 
Source Error:
 

Line 894: for (int j=0; j<Items[i].Cells.Count; j++)
Line 895: {
Line 896: HtmlSelect select = (HtmlSelect)list[j]; //<== This is Error: list.count = 0 :confused:
Line 897: if (select.SelectedIndex > 0)
Line 898: {

AnswerRe: Error !?memberstefano piuri24 May '06 - 23:48 
In this first (rudimental) version you need to reload the control each time you do a selection, so ArrayList list is not empty.
I will release a better release in future.
 
Best regards. Stefano

GeneralRe: Error !?membergetjacob7 Nov '06 - 19:32 
***************
In this first (rudimental) version you need to reload the control each time you do a selection, so ArrayList list is not empty.
***************
 
How to reload the control each time ??????
Pls Help

GeneralRe: Error !?memberstefano piuri9 Nov '06 - 5:34 
You should bind data every time you select a filter, because data are not stored in the control.
I will try to do this by firing an event when the selction change, but this time I am very busy.
 
Sorry.
Stefano
 

GeneralUselessmembernsimeonov17 May '06 - 16:15 
Why? Because you may need filtering when you have a large dataset. However in this case you will want to use paging instead of displaying everything on one page - it's a web page, not a regular windows form and is suppose to be downloaded and processed by a browser. A 20mb page will just kill your server and then your browser for a while and I don't even want to mention the time and traffic costs.
 
Also you are adding dropdown lists on every column and this is wrong (I know excel does but it's a desktop application not a web page). So if you have a list of customers and cities - filtering by cities is ok while filtering by customer name is useless, however you will have a combo box with a huge list.
 
And last - you're populating the lists based on the displayed data and thus rendering the paging option unusable. I'm not sure how you tested this control but try a larger dataset - say 50,000 items - and chech how long does it take to display the page.
 
If you have less than 100 items it's easier to implement a sort feature and scroll through the list however with more than 100 items your control will generate too much traffic to be worth using it.
 
Filtering would be nice however if you do it like google suggest does - put input boxes, when typing something display a list of suggestions (look here) and when you select something - then you may filter the list - this way you will be able to page your dataset and also save traffic from the dropdown lists.
 
-- modified at 22:19 Wednesday 17th May, 2006
AnswerRe: Uselessmemberstefano piuri17 May '06 - 23:05 
Thank for your comments.
 
More the 50,000 items or less then 100 items ? I am agree with you, this control is not the solution. Each control have to be used in his correct way: if you load 30,000 items in a dropdown list, or if you page a datagrid with only one item per page, or if you put 100 words in a button caption (and many other crazy examples), you will probably have some problems.
 
The typical scenario for my control is when you have 100 – 200 items (for example customers orders) which can be divided in 5 – 10 clusters (customers number) and you wish select a customer and then sort its orders by quantity: paging data do not help you; sort by customer name and then sort by quantity and then scroll the datagrid to search a customer is not good for the final user.
Instead, select a customer and the sort by quantity is more easy and comfortable for the final user (so they have said to me).
 
Best regards.

 
Stefano
GeneralIt seams to looking very goodmemberRehan Hussain15 May '06 - 19:18 
It seams to look very good, i am unable to run this. please any one tell me how could i run this project. I am facing error
Configuration Error
Line 44: by Microsoft that offers a single logon and core profile services for member sites.
Line 45: -->
Line 46:
Line 47:
Line 48: <!-- AUTHORIZATION
GeneralRe: It seams to looking very goodmemberstefano piuri15 May '06 - 21:29 
Can you send more details for this error ?
The error is in the source or in the demo project ?
The error comes during loading or executing ?
 
Bye. Stefano

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 13 May 2006
Article Copyright 2006 by stefano piuri
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid