LANGUAGE: VB .NET
Find Controls With _ctl
When you just can't get the reference you need, this trick can be a lifesaver.
By Don Kiely
In my first production ASP.NET application, the project's Web designer created a beautiful, highly usable design. Users loved it, but it was a bear to code. The hard part was that the app frequently had to grab a reference to an individual control embedded within a DataGrid or DataList. For example, the design required programmatic interaction with server controls located deep within a HeaderTemplate (yes, we had controls in the header), ItemTemplate, and EditItemTemplate within a DataList control. I had to do things such as populate drop-down lists in a single row of the DataGrid or DataList when the user clicked on a button that fired the EditCommand event. This was gnarly stuff, particularly because I started coding the app during the beta phase of .NET with, um, incomplete documentation.
(Note: If the previous paragraph made no sense, read the documentation for how DataGrids, DataLists, and Repeater server controls work. You also should look at the HTML these controls produce.)
As you now know (because you have examined the HTML from various states of DataGrid and DataList controls), ASP.NET identifies each HTML control with a unique ID - a three-part name. In the .aspx page, if the DataList is called dlProjections, the control I'm interested in is called txtPositionID, and the user has opted to edit the second record listed, the source in the browser will have the name attribute on the <input> element with a value of dlProjections:_ctl2:txtPositionID.
The center part of the colon-delimited name, _ctl2, is the key to getting programmatic access to the control. The "_ctl" is the default unique name for the control, with the row number appended. (It's a zero-based value, with zero representing the header row.) Because the user clicked on the edit button of the second row in the DataList in this case, the middle portion of the unique name is _ctl2.
So how do you use this? In your code, you obviously know the name of the DataGrid or DataList control, the name of the control you want, and in most events you have access to the index of the row with the second parameter passed into the event (usually with a variable name of e). Here's an example of the many ways you can put this to use.
The procedure, in this case the EditCommand event procedure, starts by getting the index of the row using e.Item.ItemIndex. Then it builds a string of the form "_ctl2" and uses multiple levels of the FindControl method to drill down into the hierarchy of controls in the DataList (in this case) for the control you want:
Private Sub dlIndustries_EditCommand(ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataListCommandEventArgs) _
dlCompanies.EditItemIndex = e.Item.ItemIndex
BindDataList() 'bind the data and display it
Dim ctl As String = "_ctl" & (e.Item.ItemIndex + 1).ToString
Dim ddl As DropDownList
ddl = CType(dlCompanies.FindControl(ctl).FindControl("lstRegionUpdate"), DropDownList)
Now ddl has a reference to the control you want, and you can manipulate it as any other control.
This isn't a technique you want to use as a first step. Many times FindControl will zero right into the control you want. But if you can't get the reference you need that way, this trick can be a lifesaver.
Don Kiely is senior information architect for Third Sector Technologies, a business and technology consultancy in Fairbanks, Alaska. When he isn't living and breathing ASP.NET and XML, he is exploring the Alaska wilderness with his dog Mardy, hiking, whitewater kayaking, skiing, and searching for true love. Reach him at mailto:[email protected].