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

E

Eli Gassert

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top