An Extensive Examination of the DataGrid Web Control: Part 9, Part 2
By Scott Mitchell
In Part 1 we looked at what is needed to set the focus to an
HTML input field - namely, some client-side code that references the input field and calls its
focus()
method. We also took a quick look at our DataGrid's declaration. In this part
we'll look at how to dynamically add the needed client-side code to the ASP.NET Web page when a
row is selected for editing!
Dynamically Adding Client-Side Code to an ASP.NET Web Page
When one of the rows of the DataGrid is selected for editing, we need some way to insert client-side code. Recall that we want to do this all within a client-side JavaScript function. There are two ways to do this. One way is to hard-code in the JavaScript function, having it's body be an ASP.NET Literal control. That is, we'd have something like:
|
Note that here the setFocusIfNeeded()
JavaScript function will be called on every page
load. For those times that we wish to have some sort of client-side action occur, we'd simply set the
ltlScript
control's Text
property to the script we wished to have execute.
Another way to accomplish this is to use the Page
class's RegisterStartupScript
method. This method takes two string parameters, a key and the client-side script to emit. It then
adds a client-side script block at the end of the ASP.NET page and includes in it the client-side script
provided. With this approach we would not use an onload
event handler as we did above -
rather, we'd only call the RegisterStartupScript
method when the focus needed to be set (since
the client-side JavaScript would only be emitted when this method call was made).
I will use the latter approach - personally I find it to be cleaner and more readable.
When the "Edit" Button is Clicked...
When the "Edit" button is clicked we need to somehow emit client-side code that will set the focus to the TextBox in the EditItemTemplate. As we saw in Part 6, the DataGrid exposes a
EditCommand
event that fires whenever the "Edit" button is clicked.
We can then provide an event handler for this EditCommand
event.
Inside of this event handler we want to, as always, set the DataGrid's EditItemIndex
property
and rebind the DataGrid. Furthermore, after we've performed these first two steps, we want to emit
the necessary client-side code to set the focus to the EditItemTemplate's TextBox. In order to set
the focus we need to grab the Web form's ID
and the TextBox's ClientID
.
We can then emit JavaScript like: FormID.TextBoxID.focus();
.
Below you can see the code for the DataGrid's EditCommand
event handler.
|
Notice that we need to retrieve the ClientID
of the TextBox in the EditItemTemplate.
Hence, immediately after setting the DataGrid's EditItemIndex
property and calling
the BindData()
method (the first two lines of the event handler), we create a local
variable named descTB
and set it equal to the TextBox control in the 3rd column
of the DataGrid row that is being edited. We use the FindControl
method to find
the control named txtDesc
, which is the name of our TextBox control in the EditItemTemplate.
You may be wondering why we are using dgPopularFAQs.Items(e.Item.ItemIndex).Cells(2).FindControl("txtDesc")
and not just e.Item.Cells(2).FindControl("txtDesc")
. This is because when the e.Item
DataGridItem
instance was passed in, the row was not in its editing form, meaning
that the TextBox specified in the EditItemTemplate is not present. After we call the
BindData()
method (which rebinds the DataGrid, calling the DataBind()
method) the
e.Item
DataGridItem
instance still refers to the old, non-editable form.
Hence, we have to work directly with the DataGrid's Items
property, extracting the correct
DataGridItem
instance (which is given by e.Item.ItemIndex
).
Once we have a reference to this TextBox control, we can go ahead and emit the client-side JavaScript
code using the RegisterStartupScript
method. Note that we have to include the actual
script
tags, and that the closing script
must be broken up into two
strings (i.e., "<" & "/script>"
). If it is not, the ASP.NET parsing engine will
be confused when it reaches that closing script
block and generate an error.
In the RegisterStartupScript
method you may have noticed that we are referencing the TextBox's ClientID
property as opposed to its
ID
property. This is because the TextBox control is a child control of the DataGrid row and
the DataGrid row is a child of the DataGrid. With each increasing child layer, ASP.NET augments the
UniqueID
of the controls, prefixing it with the parent's ID
. For example,
our TextBox's ID
property is txtDesc
(the value we gave it in our DataGrid's
declaration), but it's UniqueID
is something like: dgPopularFAQs:_ctrl4:txtDesc
.
The ClientID
, which is the property we're interested in, is the actual value of the rendered
HTML tag's id
property, which is the UniqueID
with colons replaced with underscores.
That is, the ClientID
for the TextBox would be something like:
dgPopularFAQs__ctrl4_txtDesc
.
The actual JavaScript emitted by the RegisterStartupScript
method looks something like:
<script language="JavaScript"> frmEditFAQs.dgPopularFAQs__ctl12_txtDesc.focus(); frmEditFAQs.dgPopularFAQs__ctl12_txtDesc.select(); </script>
The select()
call is optional - it simply highlights all of the text in the TextBox. Feel
free to omit this call if so desired. Take a moment to try out the live
demo and observe the behavior when a row's "Edit" button is clicked. Also, you are encouraged to
do some View/Sources on the live demo so as to see the emitted JavaScript block as well as the
id
and name
attributes of the HTML rendered for the TextBox in the
EditItemTemplate.
Conclusion
In this article we examined how to programmatically add some client-side code to the DataGrid's
EditCommand
event in order to have a TextBox in the EditItemTemplate receive focus when
the "Edit" button for a row is clicked.
Happy Programming!