DataGrid Foreign Event Handling
By Andrew Ventura MCAD/MCSD (.NET) & MCSE
Published: 2/18/2003
Reader Level: Beginner
Rated: 4.75 by 4 member(s).
Tell a Friend
Rate this Article
Printable Version
Discuss in the Forums

Easy ways to wire up foreign events to a DataGrid

Download C# Sample Code

Introduction and Overview

DataGrids seem to be very popular among all ASP.NET developers these days. I've seen whole series of articles and a lot powerful custom controls released for it. I personally think they are great as long as you manage your Viewstate size and don't try to think too much outside the box, or grid in this case. Anyhow, one thing that has bothered me is that it isn't easy to wire up events like, OnSelectedItemIndexChange, in template columns containing controls like the RadioButtonList or DropDownList. They just don't seem to play well with the DataGrid like the LinkButton or ImageButton.

If you are using VS.NET and try to view events of a RadioButtonList control, you'll notice that the lighting bolt is no where insight. That implyed to me that you couldn't wire up any events to that object. One of my partners pointed out to me that it would be impossible for the IDE to wire up the event in the CS, because that object is created until the DataGrid crated on the page. With that in mind we both decided that we should just be able to intercept on the OnItemDataBound and wire up the event right there and we would be all set. Much to his and my surprise the event never fired, and all the news groups just said "make sure autopostback is enabled", well.. duh! Anyhow my partner came up with a quick fix by adding some javascript to the drop-down list that fired the onClick on a LinkButton that had no text which was rendered as an empty href. Ugly, but it worked.

I dug a little deeper and moved our intercept code to the OnItemCreate event of the DataGrid. Like magic everything started working, why it doesn't work in the DataBind still puzzles me. I thought back to early PDC bits of ASP.NET when there was no VS.NET and remembered wiring my events right in the tag itself. I guess I've gotten lazy with VS.NET and letting it register all my events progamatically. I wired the event on the ASPX side and changed its accessibility from private to protected and the event on the DropDownList fired without having to implent it on the DataGrid onItemCreate. The only problem we had now was how to figure out which row the event came from on the DataGrid.

How do I find out which row on the DataGrid the event was fired from?

All DataGrid Command Events use the DataGridCommandEventArgs which has a nice reference to the command source of the event. A lot of useful information can be found there such as ItemIndex and the DataItem. Events like OnSelectedIndexChanged found in controls like the RadioButtonList and CheckBoxList can't be wired into the ItemCommand event of the Datagrid. This presents a problem when trying to get to the row of the Control that just kicked off an event. I've solved this problem two ways, one home grown method and another method that takes advantage of the control heichary of ASP.NET.

Heirchary Method

Using the .Parent of a control returns its containing control. Each control in a templated column in a DataGrid lives in a TableCell which lives in a DataGridItem. So the quickest way to get to the DataGridItem is to just do a .Parent.Parent and cast the object into a DataGridItem and you'll have all the same information that is contained in the DataGridCommandEventArgs.Item. Things can get tricky if you have another container control like a Panel, but you should always be able to walk up the tree to get to the DataGridItem.

Helper Function Method

I'm not a big fan of this method even though I wrote it, but it will return the DataGridItem as well. Each Control on a ASP.NET page has a property called ClientID. There is a very logical naming pattern for controls within a DataGrid and this method just parses the ClientID and returns the DataGridItem based on the index of the ClientID. Not pretty, but it works. Just cut and paste and pass in the controls ClientID and the DataGrid the control is located on.

private DataGridItem GetDataGridItem(string pClientID, DataGrid pDataGrid)
{
	string myRowID = pClientID;
	myRowID = myRowID.Substring(myRowID.IndexOf("__ctl")+5);
	myRowID = myRowID.Substring(0,myRowID.IndexOf("_"));

	if (pDataGrid.ShowHeader)
		return pDataGrid.Items[int.Parse(myRowID)-2];
	else
		return pDataGrid.Items[int.Parse(myRowID)-1];
}

A DataGrid can only have one "Edit Item" at a time, so how often would I have more than one drop-down list?

Some people are stuck in the mode of only editing one item at a time in a DataGrid. That can be come painfully slow for some interfaces and force the user to constantly click Edit & Update buttons over and over. It is perfectly legal and logical to put a drop-down list or RadioButtonList in the ItemTemplate portion of a Template Column. The Sample application included with this How-To has three DataGrids with three seperate shopping lists. Items within each shopping list can be moved to any other list. This interface quickly allows items to be moved between the three grids without having to click edit and update over and over.

The sample application shows all the ways I talked about above in how to implement Foreign Event capturing on a DataGrid. One method registers the event on the ASPX side, the second registers the event on the OnItemCreate and the third creates the control and adds the event all in the OnItemCreate.

A Screen Shot of the Sample Application


Final Thoughts

I'm still not quite sure why Microsoft hides the events icon, you would think the IDE would have the smarts to place the event in the tag or the codebehind. Also, I'm not quite clear why you can't wire the event on the onItemDataBound.

Something to remember about DataGrids is that they are very ViewState heavy. Most people find out when they disable ViewState on an DataGrid most of their functionality goes away, like paging. The best way to control ViewState size is to convert all your bound columns to template columns and disable ViewState on your Labels. Another thing that takes up ViewState are the Edit, Update, Delete & Cancel Buttons. Convert those columns and disable ViewState on those buttons, you don't need ViewState on those buttons to make them work, unless you do some mods to them on your codebehind! Good Luck and Happy Coding!



Marketplace
(Sponsored Links)
What are the green links?
   



 
Copyright © 2007 CMP Tech LLC |
Privacy Policy (4/10/06) | Your California Privacy Rights (4/10/06) | Terms of Service | Advertising Info | About Us | Help