Custom web control - Unable to capture events with AddHandler in an ITemplate

Discussion in 'ASP .Net Datagrid Control' started by Eli Gassert, Jun 11, 2004.

  1. Eli Gassert

    Eli Gassert Guest

    Ok, I know this has been asked a lot. And I see a lot on the topic,
    but things are a little different here and it's still not quite
    working for me. I've been at this for 3 days straight, averaging 13
    hours a day so I have no idea what to do anymore :(

    Basically here's the scenario:
    My datagrid class is called MyDataGrid. It is a custom web control
    and is defined as follows:
    Public Class MyDataGrid
    Inherits WebControl
    Implements INamingContainer

    The datagrid itself is defined as:
    Private WithEvents _Grid As New DataGrid

    The main two datagrid colums are defined as follows:
    [ITemplate-LinkButtons,[ITemplate-MyDataGrid & Label, EditItemTemplate
    is a set of DropDownLists with AutoPostBack=True]

    Now, here's where it gets tricky. If the data passed in is of one
    type, it shows the label by hiding MyDataGrid. Otherwise, it shows
    MyDataGrid in the column and passes it the data.

    Consider this a tree view.

    For the intial MyDataGrid object, which is declared in an aspx where
    it's used, everything works -- the link buttons, the AutoPostBack
    retaining state, etc. But for all of the sub-MyDataGrids, it fails to
    keep state. The Delete and Edit link buttons still work, but once I'm
    in edit mode, any post back causes the page to go back to before the
    edit command was even registered.

    Maybe I don't know what I'm doing -- this is my first web control. If
    no one can actually help on this topic, could someone please just
    explain to me the order of operations that I should be using here?
    Like where and when should I set the datasource in the aspx page.
    When and How should I add the handlers to items that are dynamically
    created for each row (ie grid, label, drop down list) so that all
    nesting works for these items and viewstate is retained?

    ' passing in profileFilter allows the sub-data of the parent grid to
    be set
    ' for the new grid
    Public Sub New(Optional ByVal parent As ProfileFilterDataGrid =
    Nothing, Optional ByVal profileFilter As ListrakXML.CProfileFilter =
    Nothing)
    MyBase.New()

    If Not profileFilter Is Nothing Then
    DataSource = profileFilter.GetXML()
    End If

    _Parent = parent
    End Sub

    Private Sub Grid_Init(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Init
    InitGrid()
    End Sub

    Public Sub InitGrid()
    ' sets up all the columns, viewstate, header style, etc
    end sub

    Private Sub BindData()
    ' sets up a datatable and saves it to the viewstate (does _not_ set
    the DataSource or call DataBind)
    end sub

    Public Shadows Property DataSource() As String
    ' Takes a custom datasource of an XML string
    end property

    ' the datatable at the bottom is for debugging purposes
    ' note how in each iteration, I have to re-set the datasource
    ' even though ViewState is enabled. Otherwise, _none_ of the
    ' datagrids repopulate correctly, not even the main one!
    ' but I only bind to the table stored in the ViewState (actually,
    ' it's stored in the cache) once
    Protected Overrides Sub CreateChildControls()
    Controls.Add(_Grid)

    If Not Page.IsPostBack Then
    If _Parent Is Nothing Then
    'clear out the cache
    Dim item As IDictionaryEnumerator
    item = Page.Cache.GetEnumerator()
    While (item.MoveNext)
    Page.Cache.Remove(item.Key)
    End While
    End If

    BindData()
    End If

    _Grid.DataSource = Data
    _Grid.DataBind()

    If _Parent Is Nothing Then
    Dim grd As New DataGrid
    grd.DataSource = Data
    grd.DataBind()
    grd.AutoGenerateColumns = True
    Controls.Add(grd)
    End If
    End Sub

    Private Sub Grid_OnItemCommand(ByVal sender As Object, ByVal e As
    DataGridCommandEventArgs) Handles _Grid.ItemCommand
    ' handles all my commands
    end sub

    ' This is the column that shows the MyDataGrid or Label column
    ' but when in edit mode, it shows drop down lists

    Public Class XMLDataColumn
    Implements ITemplate
    Implements INamingContainer
    Public Class XMLDataColumn
    Implements ITemplate
    Implements INamingContainer

    Private WithEvents _Grid As ProfileFilterDataGrid
    Private _Type As ListItemType

    Private cboHeaders As DropDownList
    Private cboAttributes As DropDownList
    Private cboCompareTypes As DropDownList
    Private txtValue1 As TextBox
    Private txtValue2 As TextBox
    Private valValue1 As RequiredFieldValidator
    Private valValue2 As RequiredFieldValidator

    ' ItemTemplate stuff
    Private dgrGrid As ProfileFilterDataGrid
    Private lblText As Label

    Public Sub New(ByVal grid As ProfileFilterDataGrid, ByVal type As
    ListItemType)
    _Grid = grid
    _Type = type
    End Sub

    Public Sub InstantiateIn(ByVal container As System.Web.UI.Control)
    Implements System.Web.UI.ITemplate.InstantiateIn
    ' Edit Template
    cboHeaders = New DropDownList
    cboAttributes = New DropDownList
    cboCompareTypes = New DropDownList
    txtValue1 = New TextBox
    txtValue2 = New TextBox
    valValue1 = New RequiredFieldValidator
    valValue2 = New RequiredFieldValidator

    ' ItemTemplate stuff
    dgrGrid = New ProfileFilterDataGrid(_Grid)
    lblText = New Label

    lblText.ID = "lblText"
    dgrGrid.ID = "dgrGrid"
    dgrGrid.EnableViewState = True

    container.Controls.Add(lblText)
    container.Controls.Add(dgrGrid)

    If cboHeaders.Items.Count = 0 Then
    Dim conn As New
    SqlClient.SqlConnection("Server=sql.listrak.com;Database=Listrak;uid=sa;pwd=ou8122k3;")
    Dim ds As New DataSet
    Dim da As SqlClient.SqlDataAdapter
    Dim cmd As New SqlClient.SqlCommand
    Dim dtRow As DataRow

    conn.Open()

    cmd.Connection = conn
    cmd.CommandText = "SELECT * FROM profile_label WHERE listID = '"
    & _Grid.ListID & "'"
    cmd.CommandType = CommandType.Text

    da = New SqlClient.SqlDataAdapter(cmd)
    da.Fill(ds)


    cboHeaders.Items.Add(New ListItem("-Header-", "--------"))

    For Each dtRow In ds.Tables(0).Rows
    cboHeaders.Items.Add(New ListItem(dtRow("title"),
    UCase(dtRow("title"))))
    Next

    conn.Close()

    ' first post back, hide all
    cboAttributes.Visible = False
    cboCompareTypes.Visible = False
    txtValue1.Visible = False
    txtValue2.Visible = False

    End If

    With cboHeaders
    .ID = "cboHeaders"
    .AutoPostBack = True
    .EnableViewState = True
    End With

    AddHandler cboHeaders.SelectedIndexChanged, AddressOf
    Me.OnHeaderChanged
    container.Controls.Add(cboHeaders)

    With cboAttributes
    .ID = "cboAttributes"
    .AutoPostBack = True
    .EnableViewState = True
    End With

    AddHandler cboAttributes.SelectedIndexChanged, AddressOf
    Me.OnAttributeChanged
    container.Controls.Add(cboAttributes)


    With cboCompareTypes
    .ID = "cboCompareTypes"
    .AutoPostBack = True
    .EnableViewState = True
    End With

    AddHandler cboCompareTypes.SelectedIndexChanged, AddressOf
    Me.OnCompareTypeChanged
    container.Controls.Add(cboCompareTypes)

    txtValue1.ID = "txtValue1"
    txtValue2.ID = "txtValue2"
    txtValue1.EnableViewState = True
    txtValue2.EnableViewState = True

    container.Controls.Add(txtValue1)
    container.Controls.Add(txtValue2)

    valValue1.ID = "valValue1"
    valValue1.ErrorMessage = "<BR>Text field is required"
    valValue1.ControlToValidate = "txtValue1"
    valValue1.Display = ValidatorDisplay.Dynamic

    valValue2.ID = "valValue2"
    valValue2.ErrorMessage = "<BR>Second Text field is required"
    valValue2.ControlToValidate = "txtValue2"
    valValue2.Display = ValidatorDisplay.Dynamic

    'container.Controls.Add(valValue1)
    'container.Controls.Add(valValue2)

    If _Type = ListItemType.Item Then
    dgrGrid.Visible = True
    lblText.Visible = True
    cboHeaders.Visible = False
    cboAttributes.Visible = False
    cboCompareTypes.Visible = False
    ElseIf _Type = ListItemType.EditItem Then
    dgrGrid.Visible = False
    lblText.Visible = False
    cboHeaders.Visible = True
    'cboAttributes.Visible = True
    'cboCompareTypes.Visible = True
    End If

    AddHandler container.DataBinding, AddressOf Me.OnDataBinding
    End Sub

    Public Sub OnDataBinding(ByVal sender As Object, ByVal e As
    EventArgs)
    Dim container As DataGridItem
    Dim row As DataRowView
    Dim data As RowData

    If _Type = ListItemType.Item Then
    container = CType(dgrGrid.NamingContainer, DataGridItem)
    ElseIf _Type = ListItemType.EditItem Then
    container = CType(cboHeaders.NamingContainer, DataGridItem)
    End If

    row = CType(container.DataItem(), DataRowView)

    AddHandler cboHeaders.SelectedIndexChanged, AddressOf
    Me.OnHeaderChanged

    If row("Type") = RowData.DataType.Filter Then
    Dim filter As New ListrakXML.CProfileFilter
    filter.SetXML(row("Data"))
    data = New RowData(filter)
    Else
    Dim rec As New ListrakXML.CProfileFilterRecord
    rec.SetXML(row("Data"))
    data = New RowData(rec)
    End If

    If _Type = ListItemType.Item Then
    If data.Type = RowData.DataType.Record Then
    Dim record As ListrakXML.CProfileFilterRecord = CType(data.Data,
    ListrakXML.CProfileFilterRecord)
    lblText.Text = "" & _
    "<table>" & _
    " <tr>" & _
    " <td>&lt;&lt;" & data.HeaderName & "\" & data.AttributeName &
    "&gt;&gt</td>" & _
    " <td>" & data.CompareType & "</td>" & _
    " <td>" & data.FormattedValues & "</TD>" & _
    " </tr>" & _
    "</table>"

    lblText.Visible = True
    dgrGrid.Visible = False
    Else
    dgrGrid.Parent = _Grid
    dgrGrid.DataSource = CType(data.Data,
    ListrakXML.CProfileFilter).GetXML()
    lblText.Visible = False
    dgrGrid.Visible = True
    End If
    ElseIf _Type = ListItemType.EditItem Then

    If Not cboHeaders.Items.FindByValue(UCase(data.HeaderName)) Is
    Nothing Then
    cboHeaders.SelectedValue = UCase(data.HeaderName)
    PopulateAttributes()
    End If

    If cboHeaders.SelectedIndex <> 0 Then
    cboAttributes.Visible = True

    If Not cboAttributes.Items.FindByValue(UCase(data.AttributeName))
    Is Nothing Then
    cboAttributes.SelectedValue = UCase(data.AttributeName)
    PopulateCompareTypes()
    End If

    If cboAttributes.SelectedIndex <> 0 Then
    cboCompareTypes.Visible = True

    Dim rec As ListrakXML.CProfileFilterRecord = CType(data.Data,
    ListrakXML.CProfileFilterRecord)

    If Not cboCompareTypes.Items.FindByValue(rec.CompareType) Is
    Nothing Then
    cboCompareTypes.SelectedValue = rec.CompareType
    End If

    ' txtValue1/txtValue2 visibility designated in PopulateValues()
    If rec.GetValueCount() > 0 Then
    txtValue1.Text = rec.GetValue(0).Text

    If rec.GetValueCount() > 1 Then
    txtValue2.Text = rec.GetValue(1).Text
    End If
    End If

    End If
    End If

    End If
    End Sub

    ' actual handler functions left out...
    end class
    Eli Gassert, Jun 11, 2004
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Luhar Powell via .NET 247
    Replies:
    0
    Views:
    2,443
    Luhar Powell via .NET 247
    Apr 1, 2005
  2. LaptopHeaven
    Replies:
    0
    Views:
    405
    LaptopHeaven
    Oct 5, 2006
  3. Luhar Powell via .NET 247

    Newbie:Access custom Itemplate(not datagrid/repeater/datalist) control values on postback

    Luhar Powell via .NET 247, Apr 1, 2005, in forum: ASP .Net Building Controls
    Replies:
    0
    Views:
    212
    Luhar Powell via .NET 247
    Apr 1, 2005
  4. Using ITemplate as property of a custom control

    , Jan 24, 2007, in forum: ASP .Net Building Controls
    Replies:
    3
    Views:
    512
    Peter Zolja
    Jan 31, 2007
  5. Luhar Powell via .NET 247
    Replies:
    0
    Views:
    162
    Luhar Powell via .NET 247
    Apr 1, 2005
Loading...

Share This Page