Link to home
Start Free TrialLog in
Avatar of Headspace
Headspace

asked on

dynamic bound template columns in a web datagrid using VB.NET

Hi there,

I'm trying to create a class to use as a template for custom bound columns in a web server control datagrid, and I'm about to pull my hair out.  I've used the MSDN documentation to successfully write a class that will create any template column that I define in the main page, but I can't figure out how to add databinding to the item and editItem Item Types (which contain a label and a textbox, respectively).  I've been attempting to add an event handler within the new template class that will bind each of these, but haven't had any luck.  Can anybody provide me with an example that will allow me to add a custom template column to a web server datagrid programmatically?

Thanks in advance!
Avatar of Headspace
Headspace

ASKER

ok...well, either this was extraordinarily elementary, or nobody knows what the heck I'm talking about (or perhaps nobody cares!).  Anyway, I'll answer my own question, and post the code in case somebody else needs an example.

Public Class DataGridTemplate
    'muy importante.  Without implementing the ITemplate, the new columns will have no method
    'to implement the populating of the datagrid.
    Implements ITemplate
    'declare a listItemType variable to cover all of the datagrid template column item types, and then
    'set up any other variables that might be necessary to create the template column(s).
    Dim templateType As ListItemType
    Dim columnName As String
    Dim bindingName As String

    Sub New(ByVal type As ListItemType, ByVal colName As String, ByVal bndName As String)
        'set up the case select, and then create some variables to hold data for column
        'header names and (if they're different) column binding names.
        templateType = type
        columnName = colName
        bindingName = bndName
    End Sub

    Sub InstantiateIn(ByVal container As Control) Implements ITemplate.InstantiateIn

        'case select for various listitem types.

        Select Case templateType
            'gotta have a header!
        Case ListItemType.Header
                'set up the Header column.
                Dim lc As New Literal
                lc.Text = columnName
                container.Controls.Add(lc)
            Case ListItemType.Item
                'use a label to display data in each cell of the column.
                Dim lbl As New Label
                lbl.ID = "lbl" & bindingName
                lbl.CssClass = "label"
                'if it's bound, add an event handler to create the databinder.
                AddHandler lbl.DataBinding, AddressOf TemplateControl_DataBindinglbl
                container.Controls.Add(lbl)
            Case ListItemType.EditItem
                'finally, add an edit Item that uses a textbox (to allow for editing, of course).
                Dim txt As New TextBox
                txt.ID = "txt" & bindingName
                txt.CssClass = "textbox"
                'databinder event handler, just like the label in the Item case.
                AddHandler txt.DataBinding, AddressOf TemplateControl_DataBindingtxt
                container.Controls.Add(txt)
        End Select
        'Footer Items?! We don't need no stinkin' Footer Items!
    End Sub

    Private Sub TemplateControl_DataBindinglbl(ByVal sender As Object, ByVal e As System.EventArgs)
        'create a label to reference the label in the newly created column.
        Dim lbl As Label
        lbl = CType(sender, Label)
        'create a container to reference the label's container...
        Dim container As DataGridItem
        '...and then set the reference.
        container = CType(lbl.NamingContainer, DataGridItem)
        'watch out for null values!
        Try
            lbl.Text = DataBinder.Eval(container.DataItem, lbl.ID)
        Catch exc As Exception
            lbl.Text = "" 'if all else fails, at least the column will contain an empty cell rather than completely fail.
        End Try
    End Sub

    Private Sub TemplateControl_DataBindingtxt(ByVal sender As Object, ByVal e As System.EventArgs)
        '...second verse, same as the first.  Copy the sub used to add the binding event
        'to the label and change the necessary values to make it work for the textbox in
        'the editItem.
        Dim txt As TextBox
        txt = CType(sender, TextBox)
        Dim container As DataGridItem
        container = CType(txt.NamingContainer, DataGridItem)
        Try
            txt.Text = DataBinder.Eval(container.DataItem, txt.ID)
        Catch exc As Exception
            txt.Text = ""
        End Try
    End Sub
End Class

Now all one has to do is create an instance of the class in the page that the new datagrid will be created:

Private Sub buildGrid(ByVal headers As ArrayList, ByVal binders As ArrayList)
        'to keep things moving on the fly, a data table has already been created and stored to a session variable, and then
        'two array lists were used to set up the names of each datagrid column and the name of each data table column (just in
        'case they're different; one wouldn't want to display the 'LAST_NAME' data table column explicitly in the datagrid header
        'title, but perhaps 'Last Name' instead).

        'count the number of columns needed by using the header title arraylist.
        Dim i, listCount As Integer
        listCount = headers.Count
       
        'although the datagrid could be created entirely in code, it might be easier to create it in the web designer with a couple
        'of edit/delete columns and reference it at run time.
        Dim dg As DataGrid = Me.FindControl("dgEdit")
        'iterate through the header arraylist and call the class to create each new column.
        For i = 0 To listCount - 1
            Dim tCol As New TemplateColumn
            tCol.HeaderTemplate = New DataGridTemplate(ListItemType.Header, headers(i), binders(i))
            tCol.ItemTemplate = New DataGridTemplate(ListItemType.Item, headers(i), binders(i))
            tCol.EditItemTemplate = New DataGridTemplate(ListItemType.EditItem, headers(i), binders(i))
            'some formatting might be required at this point, too.
            tCol.HeaderStyle.Wrap = False
            'add the column and then move on to the next.
            dg.Columns.AddAt(i, tCol)
        Next
       
        'set the datagrid to use the current data table stored in the session variable...
        dgEdit.DataSource = Session("dt")
        '...bind it...
        dgEdit.DataBind()
        '...ensure that the user can read it...
        dgEdit.Visible = True
        '....and viola!
    End Sub

I'm afraid that if you want to be able to sort this datagrid, you're on your own; I have yet to figure that part out.
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial