December 20 2009

Fixed GridView headers with jQuery

Introduction
One of requirement these days while displaying data with GridView, is to show fixed headers and also show scrollable contents (if data is more than the visible area of browser). It is not a easy task with just HTML, CSS and ASP.Net. We need something which is more easy and less hectic. And here comes our jQuery and its plugins.

Here I am going to show how to display large amount of data in GridView with fixed headers and scrollable contents.

Why we need such a GridView ?
1. No need to scroll the entire page, when table contents exceeds the visible area of browser.
2. When you scroll contents of table, header must always be visible. As it will be easy when you have so many columns with similar data.

Step 1. Setup your web site for using jQuery

You can check my previous article to see how you can set an ASP.Net web site for using jQuery.

Step 2 . Download the plugin and set it
I will use a jQuery plugin “Chromatable”. This is a very easy plugin and woks best for ASP.Net GridView. Download plugin from here

And then place the plugni file together with jQuery core file in Scripts folder

post1
Step 3. Lets implement it
First set your page to use jQuery, plugin file and CSS –

<head id="Head1" runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>My Fixed Header Table</title>

    <script type="text/javascript" src="Scripts/jquery-1.3.2.min.js"></script>

    <script type="text/javascript" src="Scripts/jquery.chromatable.js"></script>

    <link href="App_Themes/default/style.css" rel="stylesheet" type="text/css" />
</head>

Now we have all things set up. Now I am going to add a aspx page to my web site. I named page as “FixedHeaders.aspx”. Next I will add a SQLDataSource and a GridView to my page. These two controls will display all products from my “Product” table in Northwind database.
Code will be –


<asp:SqlDataSource ID="mySqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
    SelectCommand="SELECT [ProductID], [ProductName], [SupplierID], [CategoryID], [QuantityPerUnit], [UnitPrice], [UnitsInStock], [UnitsOnOrder], [ReorderLevel], [Discontinued], [CategoryName] FROM [Alphabetical list of products]">
</asp:SqlDataSource>
<asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="mySqlDataSource" OnDataBound="myGridView_DataBound">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" />
        <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" />
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
        <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" SortExpression="ReorderLevel" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" />
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" SortExpression="CategoryName" />
    </Columns>
</asp:GridView>

For this plugin to work, I just need to do one more thing. I need to tell ASP.Net that render accessible header for my GridView. By this I mean, that there should be a
thead tag in my table ( to render header of table as thead tag). In normal case ASP.Net render gridview without a thead tag ( it just uses a tr tag with nested th for headers ).
So the code behind will look like this


protected void myGridView_DataBound(object sender, EventArgs e)
{
    myGridView.UseAccessibleHeader = true;
    if (myGridView.Rows.Count != 0)
    {
        myGridView.HeaderRow.TableSection = TableRowSection.TableHeader;
        myGridView.FooterRow.TableSection = TableRowSection.TableFooter;
    }
}

So by these lines I am asking ASP.Net
1. Use accessible headers for my GridView ( i.e render seperate thead tags )
2. Render header of columns in header of table, footers of the columns in footer of table

Now I have all things in place. Last thing I need to do is to add code to freeze header of my GridView by adding following jQuery code to my head section of page.

<script type="text/javascript" language="javascript">

    $(document).ready(function() {

        $("#<%= myGridView.ClientID %>").chromatable({

            width: "100%",
            height: "800px",
            scrolling: "yes"
        });
    });

</script>

The code is very easy. Just call chromatable() function on your GridView at the time of load of page. When I execute my page in browser, I got this output -

post3

So finally GridView has Fixed headers together with content scrolling.

Happy Programming :)

Attached Files:

  • Sample

    Sample code for this article

July 04 2009

Setup your website for using jQuery and jQuery plugins

Introduction

The moment jQuery appeared on web, everyone started using it. Specially now a days ASP.NET guys use it more and more. I love to use jQuery and jQuery plugins for my ASP.NET web sites. It made my work fun and exciting.

Before jQuery and plugins, I was a bit scared to touch JavaScript. jQuery really made an entire boring and scary thing interesting for me and many others.

So often we need to setup our web site for using jQuery and some plugins.  I am going to show you some ways how to set your web site for that.

Step 1 – Download jQuery

Always download the latest jQuery. Because this is my personal experience that with every release they improve performance and fix some bugs. get the latest jQuery from www.jquery.com.

Many of us use Visual Studio 2008 for development and “Intellisense” is our basic need. So to get intellisense, always download the .vs-doc file too. Its a documentation file for jQuery. If you will have this in your project, you will get intellisense for jQuery also. You will get all these files from download section of www.jquery.com. But remember you need to install VS Hotfix for that intellisense to work. Check this post for more information

Step 2 -Setup your web site

Now I have downloaded latest scripts. I have added folder called “Scripts” to root of web site. I will use same folder for jQuery plugins.

Scripts

Next step is to reference scripts in my master page ( I will use master page for my web site ). Some people prefer to directly add code to head section of master page. But I prefer to reference my scripts by “ScriptManager” control. It has many advantages. Like scripts file will be managed by scriptmanager, which is also taking care of other scripts.

Now I will add a ScriptManager to my master page. Its always good to have ScriptManager in your MasterPage, so that all pages in your web site will get it automatically,and you do not need to add it page by page. Next I will add a reference to my jQuery file to ScriptManager

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Site.master.cs" Inherits="MssterPages_Site" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="myScriptManager">
</asp:ScriptManager>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>

There are some other options  also in the script tag, which we will discuss later, but for now this seems good. When you will deploy your web site with debug=”false”, in your web.config file. ScriptManager will take care of your scripts automatically. The script will be cached for better performance. So now we have core jQuery set in our web site.

Step 3 -set any plugin for site wise use

Now  lets use a plugin called as “Block UI”. We will use this plugin to block the page and show a waiting message, whenever there is some AJAX activity. Check more about this very useful plugin here

Scripts_plugin

And also I have updated ScriptManager to include this plugin.  I need to do this, so that plugin will be avalable to all of my web site.


<asp:ScriptManager runat="server" ID="myScriptManager">
<Scripts>
<asp:ScriptReference Path="~/Scripts/jquery-1.3.2.js" />
<asp:ScriptReference Path="~/Scripts/jquery.blockUI.js" />
</Scripts>
</asp:ScriptManager>

I have added some code to master page to use Block UI. Check the follwing code.

<script language="javascript" type="text/javascript">
$(document).ready(function() {
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(onRequestStart)
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onRequestEnd)
});
function onRequestStart() {
$.blockUI();
}
function onRequestEnd() {
$.unblockUI();
}

</script>

This code will block the UI when AJAX will start and unblock it, when AJAX is completed

Step 4: Use a plugin for single page
There are some cases, where you need to use a jQuery plugin just for a single page. In that case adding a reference to ScriptManager on master page is not a good idea. For such a cases, I prefer to
use ScriptManagerProxy and add reference to it. This will be advantage that my plugin will be served by ScriptManager on master page, only when it has child page as the desired one. So lets do it.

Lets say I need to print a dataform on a page. The best choice for this will be using jqPrint plugin, which can print portion of page. check about it here. I have downloaded the plugin and placed it in my scripts folder

Scripts_plugin_2

I need this on page “PrintData.aspx”. I will include a ScriptManagerProxy on this page and will add a reference to it for jqPrint plugin script.


<%@ Page Title="Print this page" Language="C#" MasterPageFile="~/MasterPages/Site.master"
AutoEventWireup="true" CodeFile="PrintData.aspx.cs" Inherits="PrintData" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:ScriptManagerProxy ID="myScriptManagerProxy" runat="server">
<Scripts>
<asp:ScriptReference Path="~/Scripts/jquery.jqprint.js" />
</Scripts>
</asp:ScriptManagerProxy>
</asp:Content>

Step 5 : Test It
Now lets test our web site. Execute the default.aspx page. Now if you inspect your page with firbug for script, you will see something like this -

default

So  there is only jQuery core and Block UI scripts. Next execute the PrintData.aspx page and inspect it with FireBug, you will see something like this -

PrintData

Now you will see that for this page, you will also get the jQprint script. This is because we have specified that we will use this only on this page. Check attached code for more information.

Have fun with jQuery :)

Attached Files:

July 04 2009

Master CheckBox in GridView header

Introduction

Its common to show records from database table with GridView in ASP.Net. Once we disply records, we need to do some actions which will be applied to one, many or all records,lets say “Bulk Actions”. So we need to have a way to select records ( one or many or all ), and perform required action.

For example I am going to show all products from NorthWind database and then I will select some of them to delete or modify. The best solution in this case would be nice to have a column with CheckBox in the GridView. But if I will have 100 records in my table and I want to select all, it would be a big work for me to go and select them one by one. So lets have a master CheckBox in the header of CheckBox column.

So I am going to add a CheckBox column, with a CheckBox in header, And then use jQuery to check/un-check all of them

Setting jQuery in an ASP.NET web site

Its quite easy to set jQuery to use in ASP.NET. Put the latest Scripts in your project and reference them on your page or Master page. Doing that in Master Page is a very good option. Check the attached code for it. I am going to use ScriptManager to reference jQuery script file.

Lets Implement It!

First of all I need to show all the products in an GridView. That will be very simple. And I coded this -

<asp:SqlDataSource ID="sdsProducts" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [ProductID], [ProductName], [QuantityPerUnit], [UnitPrice], [UnitsInStock], [UnitsOnOrder] FROM [Alphabetical list of products]">
</asp:SqlDataSource>
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="sdsProducts">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<input id="masterCheck" type="checkbox" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkSelect" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
</Columns>
</asp:GridView>

I am using SQLDataSource and a GridView to Display Records.
Note that first column is a template column. In header of this column, I am using a normal HTML checkbox with an id “masterCheck”. And then an asp.net CheckBox in itemplate, with an id “chkSelect” .

<asp:TemplateField>
<HeaderTemplate>
<input id="masterCheck" type="checkbox" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkSelect" />
</ItemTemplate>
</asp:TemplateField>

So outcome will be a GridView with product list.
Products

Execute the page and check its HTML source. You will notice that id of master checkbox is same as what we have given i.e “masterCheck”. But the checkboxes in ItemTemplate will have ids like “ctl00_myBody_gvProducts_ctl02_chkSelect”. This is ASP.NET name mangling. It is going to decide how I will use jQuery selector expression.

Now we need to write jQuery code, which will Check/Un-Check all checkboxes. So I will following things
1. Find my master checkbox in gridview.
2. Attach handler for click event of master checkbox.
3. I will find all the checkboxes with id ending with “chkSelect” and assign checked state of master checkbox to them.

So this will be jQuery code produced -

<script language="javascript" type="text/javascript">
$(document).ready(function() {
  $("#masterCheck").click(function() {
    $("[id$=chkSelect]").attr('checked', $('#masterCheck').is(':checked'));
  });
});

</script>

Here is an explanation of line by line
1. Write code in document.ready event
2. Get the master checkbox and attach a function to its “click” event.
3. Find all checkboxes whoose ids are ending with “chkSelect”. I need to do this because of ASP.NET name mangling.
4. Assign checked state of master checkbox to selected checkbox.

And thats all. Once you have selected all or none, you press any button like edit, delete or hide to perform a postback. In your code behind you can loop through rows of GridView and get the values of checkbox. For example I am going to prepare a string of IDs separated by commas and display them. Check the event handler code for show button -


protected void btnShow_Click(object sender, EventArgs e)
{
  StringBuilder IDs = new StringBuilder();
  int count = gvProducts.Rows.Count;

 for (int i = 0; i < count; i++)
 {
     CheckBox chkSelect = gvProducts.Rows[i].FindControl("chkSelect") as CheckBox;
     if (chkSelect.Checked)
    {
       IDs.Append(gvProducts.DataKeys[i].Value);
       IDs.Append(",");
    }
 }
}

Conclusion

So I have used jQuery to check and un-check all the checkboxes in my GridView column. For this I am using a master checkbox with an id “masterCheck”,  and attached its click event to a function which will find all the CheckBoxes with id ending with “chkSelect”.  Once I have checkboxes, I will assign checked state of masterCheck to them. You can change master check box to ASP.NET control also, if you need to manipulate it from server side.

Happy Programming!

Update on 13-October-2009
After so many requests for both side check and un-check, I have updated the code. Now when you un-check a child checkbox, it will check or uncheck the master checkbox also ( if all are checked or un checked).
New code is


<script language="javascript" type="text/javascript">
	// for master checkbox
	$(document).ready(function() {
		$("#masterCheck").click(function() {
			isChecked = $(this).is(':checked');
			$("[id$=chkSelect]", $("#<%= gvProducts.ClientID %>")).attr('checked', isChecked);
		}
		);
	});

	// for checkboxes in GridView
	$(document).ready(function() {
		$("[id$=chkSelect]", $("#<%= gvProducts.ClientID %>")).click(function() {
			$("#masterCheck").attr('checked', allAreChecked);
		});
	});

	function allAreChecked() {
		var allCheckBoxesCount = $("[id$=chkSelect]", $("#<%= gvProducts.ClientID %>")).length;
		var allCheckedCheckBoxesCount = $("[id$=chkSelect]:checked", $("#<%= gvProducts.ClientID %>")).length;

		return (allCheckBoxesCount == allCheckedCheckBoxesCount);
	}

</script>

Attached Files:

RSS