March 3, 2021
Hot Topics:

Editing Nested DataGrids in ASP.NET

  • By Paul Kimmel
  • Send Email »
  • More Articles »

Why Can't I Edit a DataGrid Nested in a DataList?

Great. You have successfully displayed the nested DataList and DataGrid controls (see Figure 2), and when you click Edit, the DataGrid switches to edit mode. However, when you click Update, nothing happens. What could have gone wrong? Unfortunately, I am not sure about the answer to this question. It seems that the DataGrid either is not rewiring the events to each dynamically created UserControl (because the events are part of the UserControl class), or the DataGrid events aren't getting fired, or both. Whatever is happening, or perhaps is not happening, seems to be a bug. In all likelihood, you have an application to get working and don't have time to fix bugs in core Web controls. So, let's talk about a reasonable workaround.

Click here for a larger image.

Figure 2: The DataList showing Customer information and the nested DataGrid showing Contact information for each Customer.

Removing the DataList from the Equation

What does the DataList really do? From where I am sitting, it looks like, for the most part, the DataList repeats controls defined in the template. If the only control we define in the template is a UserControl, it's easy enough for you and me to load all of the UserControls we want and bind them individually. In fact, this seems to be a workable solution to our problem.

If we remove the DataList from the equation and move all of the unique controls to a UserControl, we can load an instance of our UserControl, give it some data, and add it to the page's Controls collection. This doesn't require very much code and seems to create an almost identical visual result, and, most importantly, all events seem to fire.

In Listing 5, I added a TextBox for each of the ID, First Name, Last Name, and Email address to the UserControl using an HTML table to constrain the layout. I also added the DataGrid in cell 4 followed by an image in cell 5. The new UserControl contains one templatized row. The key is to load the UserControl for each Customer object, bind the UserControl to data, and add the dynamically loaded UserControl to the Controls collection of a control on the Web Form, shown in listing 6.

Listing 5: The code-behind for the new UserControl.

Public Class NewControl
  Inherits System.Web.UI.UserControl

  [Web Form Designer Generated Code ]
  Private Sub Page_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load

  End Sub

  Private Sub BindData()
    TextBoxID.Text = ACustomer.ID
    TextBoxFirstName.Text = ACustomer.FirstName
    TextBoxLastName.Text = ACustomer.LastName
    ImagePicture.ImageUrl = ACustomer.Picture
    Datagrid2.DataSource = ACustomer.ContactInformationList
  End Sub

  Private ACustomer As Customer

  Public Property Data() As Object
    Return Data
  End Get
  Set(ByVal Value As Object)
  End Set
  End Property

  Private Sub SetData(ByVal Value As Object)
    ACustomer = CType(Value, Customer)
  End Sub

  Private Sub Datagrid2_EditCommand(ByVal source As Object, _
    ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
    Handles Datagrid2.EditCommand

    Datagrid2.EditItemIndex = e.Item.ItemIndex

  End Sub

  Private Sub Datagrid2_UpdateCommand(ByVal source As Object, _
    ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
    Handles Datagrid2.UpdateCommand

    ACustomer.ID = TextBoxID.Text
    ACustomer.FirstName = TextBoxFirstName.Text
    ACustomer.LastName = TextBoxLastName.Text
    ACustomer.Email = TextBoxEmail.Text

    ACustomer.ContactInformationList(e.Item.ItemIndex).Number = _
        CType(e.Item.Cells(2).Controls(0), TextBox).Text

    ACustomer.ContactInformationList(e.Item.ItemIndex). _
              Description = _
              CType(e.Item.Cells(3).Controls(0), TextBox).Text

    Datagrid2.EditItemIndex = -1

  End Sub
End Class

Listing 6: The code-behind that dynamically loads a UserControl for each object in my master data source.

Private Sub Page_Load(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load

  Dim ACustomer As Customer

  For Each ACustomer In CustomerList.GetCustomerList
    Dim MyControl As Control = LoadControl("NewControl.ascx")
    CType(MyControl, NewControl).Data = ACustomer
    Target.Controls.Add(New LiteralControl("<BR>"))

End Sub

Listing 5 shows that each time the UserControl gets data or its edit state changes, we rebind to all of the controls in the UserControl. The one piece left out is that we may have to devise a scheme for making the TextBox controls, such as that used to store the ID, FirstName, LastName, and Email address read only when we aren't in edit mode and writable when we are in edit mode; as an alternative, you could permit editing of the main data—a separate step from editing the grid. I will leave it for you to decide what works best in your implementation.

Listing 6 is the code that replaces the DataList. In Listing 6, Target is the name of an HtmlTableCell whose runat property is equal to server. A table cell makes a convenient place to load dynamic controls. (You also might use a control such as the PlaceHolder for this purpose.) The trick is to iterate over each object in the data source, load the UserControl, hand off the data to the UserControl, and add the UserControl to the Container's Controls collection. After finishing these few simple steps, the nested DataGrid will move easily into and out of edit mode and all events will fire correctly.

The sample in Listings 5 and 6 addresses and resolves the same functional behavior as the earlier nested DataList and DataGrid example. What isn't demonstrated is how to replicate the same visual appearance. Massaging the appearance is simply a matter of adding a style sheet and changing control properties until you get the result you desire.

The biggest drawback to not using the DataList is that you do not automatically get the different styles for item, selected item, and edit item templates. You will have to apply different styles to each of the dynamically loaded UserControls to simulate the styles associated with the various edit regions in the DataList, but this is comparatively easy to do.

Page 2 of 3

This article was originally published on June 27, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date