Filtering an ASP.NET GridView control with jQuery

Hi Friends,

This is one more story which i would like to share. some time back when i was working on web application and requirement was like wherein you need to filter the grid on the client side, so that page could be more responsive even on different kinds platforms. i figured out this cool trick to filter out the grid.

Ihave a GridView wired to some sample data. For demo simplicity I’m using an XMLDataSource and reading from an XML file in my App_Data directory.

Ihave a GridView wired to some sample data. For demo simplicity I’m using an XMLDataSource and reading from an XML file in my App_Data directory.

When the user starts to type into the Filter Text Box the rows in the table are filtered, meaning rows that don’t match the character(s) entered are hidden from view.

As the user continues to type, the list is filtered further.

The ASPX Page Markup is as follows.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master"
         AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script src="Scripts/jquery.quicksearch.js" type="text/javascript"></script>
    <script type="text/javascript">
            $(function () {
                $('input#id_search').quicksearch('table#table_example tbody tr');
             })
    </script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>
        Welcome to ASP.NET!
    </h2>
    <p>
        To learn more about ASP.NET visit
        <a href="http://www.asp.net" title="ASP.NET Website">www.asp.net</a>.
    </p>
    <input id=id_search type=text placeholder="Search"><br /><br />
    <asp:XmlDataSource ID="productsDataSource" Runat="server"
                       DataFile="~/App_Data/Products.xml">
    </asp:XmlDataSource>
    <asp:GridView ID="table_example" Runat="server"
        DataSourceID="productsDataSource" AutoGenerateColumns="False"
        ClientIDMode="Static" onprerender="table_example_PreRender">
        <Columns>
            <asp:BoundField HeaderText="ProductID" DataField="ProductID"
                            SortExpression="ProductID"></asp:BoundField>
            <asp:BoundField HeaderText="ProductName" DataField="ProductName"
                            SortExpression="ProductName"></asp:BoundField>
            <asp:BoundField HeaderText="QuantityPerUnit" DataField="QuantityPerUnit"
                            SortExpression="QuantityPerUnit"></asp:BoundField>
            <asp:BoundField HeaderText="UnitPrice" DataField="UnitPrice"
                            SortExpression="UnitPrice"></asp:BoundField>
            <asp:BoundField HeaderText="UnitsInStock" DataField="UnitsInStock"
                            SortExpression="UnitsInStock"></asp:BoundField>
        </Columns>
    </asp:GridView>
</asp:Content>
      

On line #8 we select the textbox where the user will eneter text to serve as the filter criteria and then pass as an argument to the quicksearch method the items we are filtering. In our case table rows inside a table.

 

If we run the application at this point though, we will not get the results we desire. When we start filtering we see the column header row disapear.

Take special note of line #28, specifically the “onprerender” specifier.

This event handler exists in the .aspx.cs code-behind file :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void table_example_PreRender(object sender, EventArgs e)
    {
        if (table_example.Rows.Count > 0)
        {
            table_example.UseAccessibleHeader = true;
            table_example.HeaderRow.TableSection = TableRowSection.TableHeader;
        }
    }
}

This addition to our code is very important in order to achieve the desired behavior.

 

In order to understand this we need to disect the markup that is emitted by our ASP.NET code.

First, lets look at the markup that is emitted by the GridView WITHOUT the prerender event handler.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<table cellspacing="0" rules="all" border="1" id="table_example"
       style="border-collapse:collapse;">  
   <tr>
      <th scope="col">ProductID</th>
      <th scope="col">ProductName</th>
      <th scope="col">QuantityPerUnit</th>
      <th scope="col">UnitPrice</th>
      <th scope="col">UnitsInStock</th>
   </tr>
   <tr>
      <td>1</td>
      <td>Chai</td>
      <td>10 boxes x 20 bags</td>
      <td>18.0000</td>
      <td>39</td>
   </tr>
   <tr>
      <td>2</td>
      <td>Chang</td>
      <td>24 - 12 oz bottles</td>
      <td>19.0000</td>
      <td>17</td>
   </tr>
   <tr>
      <td>3</td>
      <td>Aniseed Syrup</td>
      <td>12 - 550 ml bottles</td>
      <td>10.0000</td>
      <td>13</td>
   </tr>
   <tr>
      <td>4</td>
      <td>Chef Anton's Cajun Seasoning</td>
      <td>48 - 6 oz jars</td>
      <td>22.0000</td>
      <td>53</td>
   </tr>
   <tr>
      <td>5</td>
      <td>Chef Anton's Gumbo Mix</td>
      <td>36 boxes</td>
      <td>21.3500</td>
      <td>0</td>
   </tr>
   <tr>
      <td>6</td>
      <td>Baked Beans</td>
      <td>48 - 6 oz jars</td>
      <td>12.0000</td>
      <td>43</td>
   </tr>
   <tr>
      <td>7</td>
      <td>Buffelo Wings</td>
      <td>12 per box</td>
      <td>14.0000</td>
      <td>143</td>
   </tr>
</table>

Note that the headers, the “TH” elements live inside a standard table row “TR”.

Let’s now look at the HTML emitted by the GridView AFTER we add the preinit event handler listed above.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<table cellspacing="0" rules="all" border="1" id="table_example"
       style="border-collapse:collapse;">
   <thead>
      <tr>
         <th scope="col">ProductID</th>
         <th scope="col">ProductName</th>
         <th scope="col">QuantityPerUnit</th>
         <th scope="col">UnitPrice</th>
         <th scope="col">UnitsInStock</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>1</td>
         <td>Chai</td>
         <td>10 boxes x 20 bags</td>
         <td>18.0000</td>
         <td>39</td>
      </tr>
      <tr>
         <td>2</td>
         <td>Chang</td>
         <td>24 - 12 oz bottles</td>
         <td>19.0000</td>
         <td>17</td>
      </tr>
      <tr>
         <td>3</td>
         <td>Aniseed Syrup</td>
         <td>12 - 550 ml bottles</td>
         <td>10.0000</td>
         <td>13</td>
      </tr>
      <tr>
         <td>4</td>
         <td>Chef Anton's Cajun Seasoning</td>
         <td>48 - 6 oz jars</td>
         <td>22.0000</td>
         <td>53</td>
      </tr>
      <tr>
         <td>5</td>
         <td>Chef Anton's Gumbo Mix</td>
         <td>36 boxes</td>
         <td>21.3500</td>
         <td>0</td>
      </tr>
      <tr>
         <td>6</td>
         <td>Baked Beans</td>
         <td>48 - 6 oz jars</td>
         <td>12.0000</td>
         <td>43</td>
      </tr>
      <tr>
         <td>7</td>
         <td>Buffelo Wings</td>
         <td>12 per box</td>
         <td>14.0000</td>
         <td>143</td>
      </tr>
   </tbody>
</table>

Note that now the table row that contains the column hreaders is contained inside a “THEAD” element and the actual data rows are contained inside a “TBODY” element.

In this way the plugin can ignore the header row and leave it in place as we filter the data rows.

2,781 total views, no views today

Javascript is the bacbone of web programming!

Hi there,

This is one of the important point that one must understand Javascript is the backbone of web programming. There are so many Javascript Frameworks available in web world. But, the one which i like most is the Angular.JS. AngularJS truly in my opinion is an awesome framework. Once I started doing all the things piece by piece then it made sense to me. I think this is one of the coolest framework in SPA(Single Page App) world. With new inclusion of frameworks; sometimes you can catch it instantly when you learn it, and other times you don’t.

With this I started loving the piece instantly. Hence, decided to blog about angular. I am also working on one small assignment which will put all the pieces of Angular together  like

DataBinding, MVC, Routing, Testing, jqlite, Templates, History, Factories, ViewModel, Controllers, View, Directives, Services, Dependency Injection and Validation.

so, quite often these are basic challenges while making any SPA application. and if one core library if going to provide all the things in it then it is worth to spend time to learn this framework.

so, stay tuned in my next session we’ll talk more about angular.

Thanks,
Rahul

1,057 total views, no views today

Query String A Nightmare – Beware

Hi Friends,

Recently i was going through one problem which appeared in the production, a kind of weird one i must say, where in user has to rate the product on a scale of 1 to 10 and one malicious user just tried to trick the url. what he done is just replaced the rating to 100 and hence exception. when i was briefed about scenario and when i started figuring out the problems associated with exception i came to know about this. So, it is mandatory to validate the response which is coming from the url. It could be anything.

Thanks,
Rahul
Happy Coding

887 total views, no views today