When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Monday, September 9, 2002

An Extensive Examination of the DataGrid Web Control: Part 9, Part 2

By Scott Mitchell


  • Read Part 1

  • 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!

    - continued -

    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:

    ...
    
    <html>
    <head>
      <script language="javascript">
        function setFocusIfNeeded()
        {
          <asp:literal id="ltlScript" runat="server" />
        }
      </script>
    </head>
    <body onload="setFocusIfNeeded();">
    
    ...
    

    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.

    Sub dgPopularFAQs_Edit(sender as Object, e as DataGridCommandEventArgs)
      dgPopularFAQs.EditItemIndex = e.Item.ItemIndex
      BindData()
        
      ' Create a reference to the TextBox
      Dim descTB as TextBox
      descTB = dgPopularFAQs.Items(e.Item.ItemIndex).Cells(2).FindControl("txtDesc")
    
      'Set the script to focus and select the TextBox
      RegisterStartupScript("focus", "<script language=""JavaScript"">" & vbCrLf & _
           vbTab & "frmEditFAQs." & descTB.ClientID & ".focus();" & _
           vbCrLf & vbTab & "frmEditFAQs." & descTB.ClientID & ".select();" & _
           vbCrLf & "<" & "/script>")
    End Sub
    
    [View a Live Demo!]

    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!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article