Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dynamically load controls into a DataGrid

0.00/5 (No votes)
21 Sep 2004 1  
A method for loading a DataGrid with controls at runtime, and later allowing DataSet updates.

Sample Image - showing the concept in action!

Introduction

The ASP.NET DataGrid is a powerful control with the capability of supporting embedded controls such as text boxes, buttons, dropdown lists etc� The power of this control comes at the cost of complexity. Recently, I needed to produce a screen containing data which would be populated at run time by application users. The display format of this data could change depending on user input. Saved data might be a selection from a list, a True/False condition, or a text string. Here is an example of how the data might be viewed.

At first glance, the DataGrid control would be ideal for displaying this data. The DataGrid will accept embedded controls, however, the design and embedding is most easily accomplished within Visual Studio. My requirement is to allow the user to configure the data, and dynamically populate the screen. An additional �nice-to-have� would be to allow editing of any data field on screen with a single button to update.

Step 1 � Review of the data

For the purposes of this article, I will work with an XML file as the persistent data storage. The example used here is a serialized DataSet containing two tables, the first table � named MyDetails contains these important elements:

<myDetails>
    <name>Name</name>
    <value>Mark</value>
    <type>txtbox</type>
    <populate>NameSource</populate>
</myDetails>
  • Name: the name of the data element being stored;
  • Value: the stored value of the element;
  • Type: the control used to present the data; and
  • Populate: the secondary table used to populate the DropDownList (when type=ddl).

This example will support Textbox (�txtbox�), CheckBox (�checkbox�) and DropDownList (�ddl�) controls. In this example, the second table � named CarMake � fills the DropDownList of named car manufactures. An example of the table is provided below:

<CarMake>
    <carmake>Ford</carmake>
</CarMake>

Step 2 � Insert the DataGrid onto the ASPX screen

In my example, I am displaying two columns, the first will hold the element name, the second will hold the instance value. At this point, we will leave the grid empty. In other instances, you may wish to populate the screen at design time with controls which are data independent.

<asp:datagrid BorderWidth="1" id="dg1" 
     style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 8px" 
     runat="server" AutoGenerateColumns="False" ShowHeader="False" 
     BorderStyle="None" GridLines="Both">
  <Columns>
    <asp:TemplateColumn>
      <ItemTemplate>
      </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn>
      <ItemTemplate>
      </ItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:datagrid>

Step 3 � Bind the data to the DataGrid

It is important to bind the control even though we do not have any data elements within the control, to raise a binding event for each line of the DataSet.

        dg1.DataSource = myDS
        dg1.DataMember = "myDetails"
        DataBind()

Step 4 - Inserting the controls into the DataGrid

The trick to dynamically inserting the controls is to use the ItemDataBound event associated with the onscreen DataGrid control. The ItemDataBound event will be called for each row of data in the DataSet. When each row event is raised, the appropriate control is created and inserted into the DataGrid. This example uses the e.Item.DataSetIndex to link the DataGrid rows and the DataSource rows.

Private Sub dg1_ItemDataBound(ByVal sender As Object, _
     ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
     Handles dg1.ItemDataBound

     'ensure we are looking at an item being bound

     If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = _
                                 ListItemType.AlternatingItem Then
        'always insert the dataelement name into the first column as a label.

        Dim myLBL As New Label
        myLBL.EnableViewState = True
        myLBL.Text = dgTable(dg1).Rows(e.Item.DataSetIndex)(0)
        e.Item.Cells(0).Controls.Add(myLBL)

        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "txtbox" Then
        'insert textbox and load with data

            Dim myTB As New TextBox
            If Not IsPostBack Then
                myTB.Text = dgTable(dg1).Rows(e.Item.DataSetIndex)(1)
            End If
            e.Item.Cells(1).Controls.Add(myTB)
        End If
        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "checkbox" Then
        'insert checkbox and load with data

            Dim myCB As New CheckBox
            If Not IsPostBack Then
                If dgTable(dg1).Rows(e.Item.DataSetIndex)(1).tolower = "t" Then
                    myCB.Checked = True
                Else
                    myCB.Checked = False
                End If
            End If
            e.Item.Cells(1).Controls.Add(myCB)
        End If
        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "ddl" Then
        'insert dropdownlist and load with data

            Dim myDDL As New DropDownList
            'for simplicity I will assume the �CarMake� table 

            'always as the dropdownlist data source 


            For yy As Int16 = 0 To _
                      dg1.DataSource.Tables("CarMake").Rows.Count - 1
                myDDL.Items.Add(dg1.DataSource.Tables("CarMake").Rows(yy)(0))
            Next
            e.Item.Cells(1).Controls.Add(myDDL)

            If Not IsPostBack Then
                myDDL.SelectedIndex = _
                  CType(dgTable(dg1).Rows(e.Item.DataSetIndex)(1), Int16)
            End If
        End If
    End If
End Sub

'This function returns the table bound to the datagrid

Private Function dgTable(ByVal dg As DataGrid) As DataTable
    Return dg1.DataSource.tables(dg1.DataMember)
End Function

Step 5 � Allow full screen, single button update

Finally, we are ready to transfer the updated data back to the DataSet. This example performs the update on the prerender event. To update, we analyze the DataGrid row by row and update the DataSet accordingly.

Private Sub dg1_PreRender(ByVal sender As Object, _
         ByVal e As System.EventArgs) Handles dg1.PreRender
    ' this is where the dataset update actually happens!!

    Dim y As Int16
    'run through each line in the datagrid

    For y = 0 To dgTable(dg1).Rows.Count - 1
        'repopulate the dataset with content based on the embedded control

        If dg1.Items(y).Cells(1).Controls(0).GetType Is GetType(DropDownList) Then
            Dim myIndex As Int32 = _
              CType(dg1.Items(y).Cells(1).Controls(0), DropDownList).SelectedIndex
            dgTable(dg1).Rows(y)(1) = myIndex.ToString
        End If
        If dg1.Items(y).Cells(1).Controls(0).GetType Is GetType(TextBox) Then
            Dim myStr As String = _
                CType(dg1.Items(y).Cells(1).Controls(0), TextBox).Text
            dgTable(dg1).Rows(y)(1) = myStr
        End If
    Next
    dg1.DataSource.WriteXml(strFileLoc)
End Sub

Conclusions

This example used an XML file and offered the option of inserting only three controls. A more complete example could offer controls with specific validation (for instance, phone number or plain string).

This example did not handle events raised by the onscreen controls. This will be the subject of a future submission.

Good luck and Happy Coding!!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here