Call an Event from GridView Header

By default, you can sort on the columns of a GridView by clicking on the LinkButton in the header of a column that has a SortExpression defined. This post is going to attempt three things.

  1. Sort the column by clicking anywhere in the header cell
  2. Add a sort indicator to cells that are sortable. Cells that are sortable will have a “neutral” icon. Note in the screen capture below that UnitsInStock does not have a “neutral” icon because it does not have a SortExpression defined.
  3. Highlight the column of data that is being sorted.

gridview_clickable_headers

The idea is to add an onclick attribute that calls a javascript function to all GridView header cells that are sortable.

In the javscript function, we determine which element raised the event. If the element that raised the event is not the LinkButton, we find the LinkButton and invoke its onclick or href attribute method based on the GridView EnableSortingAndPagingCallbacks property. When the EnableSortingAndPagingCallbacks is set to true, we invoke the onclick method otherwise we invoke the method the href attribute points to.

We are checking which element raised the event in the javscript function to prevent the postback or callback from being called twice. This is because, without this check, clicking on the LinkButton will fire the method as well as bubble the event up to its parent cell causing it to be fired again (since we have added an onclick attribute to the cell). The javascript function calls the postback or callback method only if the element that raised the event is not the LinkButton.

public void MakeGridViewHeaderClickable(GridView gridView, GridViewRow gridViewRow) {

if (gridViewRow.RowType == DataControlRowType.Header)
{
for (int i = 0; i < gridView.Columns.Count; i++)
{
string sortExpression = gridView.Columns[i].SortExpression;
TableCell tableCell = gridViewRow.Cells[i];

//Make sure the column we are working with has a sort expression
if (!string.IsNullOrEmpty(sortExpression))
{
System.Web.UI.WebControls.Image sortDirectionImageControl;

//Create an instance of a Image WebControl
sortDirectionImageControl = new System.Web.UI.WebControls.Image();

//Determine the image url based on the SortDirection
string imageUrl = “~/Images/sort_neutral.gif”;

if (sortExpression == gridView.SortExpression)
{
imageUrl = (gridView.SortDirection == SortDirection.Ascending) ? “~/Images/sort_asc.gif” : “~/Images/sort_desc.gif”;
}

//Add the Image Web Control to the cell
sortDirectionImageControl.ImageUrl = imageUrl;
sortDirectionImageControl.Style.Add(HtmlTextWriterStyle.MarginLeft, “10px”);
tableCell.Wrap = false;
tableCell.Controls.Add(sortDirectionImageControl);

//Enumerate the controls within the current cell and find the link button.
foreach (Control gridViewRowCellControl in gridViewRow.Cells[i].Controls)
{
LinkButton linkButton = gridViewRowCellControl as LinkButton;

if ((linkButton != null) && (linkButton.CommandName == “Sort”))
{
//Add an onclick attribute to the current cell
tableCell.Attributes.Add(“onclick”, “RequestData(‘” + linkButton.ClientID + “‘, this, event)”);
tableCell.Style.Add(HtmlTextWriterStyle.Cursor, “hand”);
tableCell.Style.Add(HtmlTextWriterStyle.Cursor, “pointer”);
break;
}
}
}
}

}

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) {

MakeGridViewHeaderClickable(GridView1, e.Row);

}

The javascript function is shown below

<script language=“javascript” type=“text/javascript”>

function RequestData(linkId, cellElement, evt) {

var evtSource;

evt = (evt)? evt : window.event;

evtSource = (evt.srcElement)? evt.srcElement : evt.target;

//When a hyperlink is clicked, Safari returns the text node as the source element rather

//than the hyperlink. parentNode will give us the hyperlink element.

//ref: http://developer.apple.com/internet/webcontent/eventmodels.html

if (evt.target) {

if (evt.target.nodeType == 3) {

evtSource = evtSource.parentNode;

}

}

//If event was raised from an element other than the LinkButton

if ((evtSource.getAttribute(“id”) != linkId) && (evt.type == “click”)) {

//Get a collection of “a” tags inside the cell

var linkCollection = cellElement.getElementsByTagName(“a”);

for (var i = 0; i < linkCollection.length; i++) {

//If the link button has an onclick attribute, call the onclick.

//The onclick attribute is present when the GridView is using callback

//example: onclick=”java script:__gvGridSort1_GridView1.callback(…); return false;”

var onClickAttribute = linkCollection[i].getAttribute(“onclick”);

if (onClickAttribute != null) {

linkCollection[i].onclick();

break;

}

//If the link button has a href attribute, set the location of the page

//to the href value.

//The href attribute is used when the GridView is not using callbacks

//example: href=”java script:__doPostBack(‘GridSort1$GridView1′,’Sort$UnitsOnOrder’)”

var hrefAttribute = linkCollection[i].getAttribute(“href”);

this.location.href = hrefAttribute;

break;

}

}

}

</script>

You can also use this with HeaderTemplates. Just make sure your HeaderTemplate contains a LinkButton with a CommandName attribute set to “Sort” as shown below:

<asp:TemplateField HeaderText=“ProductID” SortExpression=“ProductID”>

<ItemTemplate>

<asp:Label ID=“Label1″ runat=“server” Text=‘<%# Bind(“ProductID”) %>’></asp:Label>

</ItemTemplate>

<HeaderTemplate>

<asp:LinkButton runat=“server” CommandName=“Sort” CommandArgument=“ProductID”

Text=“ProductID”></asp:LinkButton>

</HeaderTemplate>

</asp:TemplateField>

You can easily make these transparent sort icons by working at the pixel level ( I used Photoshop)
sort_asc sort_desc sort_neutral

The MakeGridViewHeaderClickable method can be placed in a Utility class if you so desire. A reference to the GridView can be obtained by using gridViewRow.Parent.Parent or (GridView) gridViewRow.NamingContainer if you don’t want to pass in a GridView reference to the method.

About these ads

, , , , , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: