Why don't child control events trigger OnBubbleEvent?

L

lisa

I have a control which contains a collection of another control. The
members of the collection can contain child controls themselves, but
these aren't coded. They are merely added between the start and end
tags of the child controls in the HTML view.

If I put a button (for instance) inside one of the child controls, the
button's click event causes a postback, but then seems to disappear
entirely. I tried looking at OnBubbleEvent in the child control and in
the parent control. Those events are never called. Nor does the
button's click event in the page containing the control ever get
called.

Is there a way to capture events of such child controls? I get the
feeling that these child controls aren't being added to the control
hierarchy of the parent control, but they are visible when I do
ParentControl.ChildrenControls(idx).Controls(idx2), so maybe they are
in the control hierarchy.

I'm completely stumped here, and I'd appreciate any suggestions.

TIA,
Lisa
 
L

lisa

It's a bit long, but here it is. I appreciate the help.

Thanks,
Lisa

Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Web.UI
Imports System.IO
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
'todo: I need to find a way to get the contained controls to postback

<ToolboxData("<{0}:TabControl runat=server></{0}:TabControl>"),
Designer(GetType(TabControlDesigner)), PersistChildren(False),
ParseChildren(True, "Tabs"), DefaultProperty("Tabs"),
DefaultEvent("SelectedIndexChanged")> _
Public Class TabControl
Inherits WebControl
Implements INamingContainer, IPostBackDataHandler,
IPostBackEventHandler

Private _tabs As New TabCollection
Private _tabsPerRow As Integer = 3
Private _tabHeight As New Unit(25, UnitType.Pixel)
Private _width As New Unit(300, UnitType.Pixel)
Private _height As New Unit(250, UnitType.Pixel)
Private _selectedIndex As Integer = 0
Private _autoPostBack As Boolean = False
Private _tabFontFamily As String = "System"
Private _tabFontSize As FontUnit = FontUnit.Point(8)
Private _tabCount As Integer

Private _tabRows As Integer
Private _fullRows As Integer
Private _tabsInPartRow As Integer
Private _tabsInFullRow As Integer
Private _fullRowTabWidth As Unit
Private _partRowTabWidth As Unit
Private _fullRowRemainder As Integer
Private _partRowRemainder As Integer
Private _tabPageHeight As Unit
Private _rowArray As Pair()()
Private _selectedRow As Integer
Private _tabIdx As Integer

Private _propertyChangedList As DropDownList

#Region "Properties"

<Category("Behavior"), Description("The collection of tabs."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty)> _
Public ReadOnly Property Tabs() As TabCollection
Get
Return _tabs
End Get
End Property

<Category("Appearance"), Description("The maximum number of tabs in
a row."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.Attribute)> _
Public Property TabsPerRow() As Integer
Get
Return _tabsPerRow
End Get
Set(ByVal Value As Integer)
If Value < 1 Then
Value = 1
End If
_tabsPerRow = Value
End Set
End Property 'TabsPerRow

<Category("Appearance"), Description("The height of each tab
row.")> _
Public Property TabHeight() As Unit
Get
Return _tabHeight
End Get
Set(ByVal Value As Unit)
If Not Value.Type = UnitType.Pixel Then
Throw New ArgumentException("TabHeight must be given in
pixels.")
End If
_tabHeight = Value
End Set
End Property 'TabHeight

<Category("Appearance"), Description("The width of the control.")>
_
Public Overrides Property Width() As Unit
Get
Return _width
End Get
Set(ByVal Value As Unit)
If Not Value.Type = UnitType.Pixel Then
Throw New ArgumentException("Width must be given in
pixels.")
End If
_width = Value
End Set
End Property 'Width

<Category("Appearance"), Description("The height of the control.")>
_
Public Overrides Property Height() As Unit
Get
Return _height
End Get
Set(ByVal Value As Unit)
If Not Value.Type = UnitType.Pixel Then
Throw New ArgumentException("Height must be given in
pixels.")
End If
_height = Value
End Set
End Property 'Height

<Browsable(False)> _
Public Property SelectedIndex() As Integer
Get
Return _selectedIndex
End Get
Set(ByVal Value As Integer)
_selectedIndex = Value
End Set
End Property 'SelectedIndex

<Category("Behavior"), Description("Whether or not the control
posts back when you change tabs.")> _
Public Property AutoPostBack() As Boolean
Get
Return _autoPostBack
End Get
Set(ByVal Value As Boolean)
_autoPostBack = Value
End Set
End Property 'AutoPostBack

<Category("Appearance"), Description("The font-family of the tab
text.")> _
Public Property TabFontFamily() As String
Get
Return _tabFontFamily
End Get
Set(ByVal Value As String)
If Value Is Nothing Then
Value = "System"
End If
_tabFontFamily = Value
End Set
End Property 'TabFontFamily

<Category("Appearance"), Description("The font-size of the tab
text.")> _
Public Property TabFontSize() As FontUnit
Get
Return _tabFontSize
End Get
Set(ByVal Value As FontUnit)
If Value.IsEmpty Then
Value = FontUnit.Point(8)
End If
_tabFontSize = Value
End Set
End Property 'TabFontSize

#End Region

#Region "WebControl Properties to Hide"

<Browsable(False)> _
Public Shadows ReadOnly Property Visible() As Boolean
Get
Return True
End Get
End Property 'Visible

<Browsable(False)> _
Public Shadows ReadOnly Property ForeColor() As
System.Drawing.Color
Get
Return System.Drawing.Color.Empty
End Get
End Property 'ForeColor

<Browsable(False)> _
Public Shadows ReadOnly Property BackColor() As
System.Drawing.Color
Get
Return System.Drawing.Color.Empty
End Get
End Property 'BackColor

<Browsable(False)> _
Public Shadows ReadOnly Property BorderColor() As
System.Drawing.Color
Get
Return System.Drawing.Color.Empty
End Get
End Property 'BorderColor

<Browsable(False)> _
Public Shadows ReadOnly Property BorderStyle() As BorderStyle
Get
Return Nothing
End Get
End Property 'BorderStyle

<Browsable(False)> _
Public Shadows ReadOnly Property BorderWidth() As Unit
Get
Return Nothing
End Get
End Property 'BorderWidth

<Browsable(False)> _
Public Shadows ReadOnly Property CssClass() As String
Get
Return String.Empty
End Get
End Property 'CssClass

<Browsable(False)> _
Public Shadows ReadOnly Property Font() As System.Drawing.Font
Get
Return Nothing
End Get
End Property 'Font

<Browsable(False)> _
Public Shadows ReadOnly Property EnableViewState() As Boolean
Get
Return True
End Get
End Property 'EnableViewState

<Browsable(False)> _
Public Shadows ReadOnly Property AccessKey() As String
Get
Return String.Empty
End Get
End Property 'AccessKey

#End Region

Protected Overrides Sub OnInit(ByVal e As EventArgs)
MyBase.OnInit(e)
If AutoPostBack And Not (Page Is Nothing) Then
Page.RegisterRequiresPostBack(Me)
End If
End Sub 'OnInit

Protected Overrides Sub LoadViewState(ByVal viewState As Object)
If Not (viewState Is Nothing) And _autoPostBack Then
_selectedIndex = Int32.Parse(CType(viewState, String))
Else
MyBase.LoadViewState(viewState)
End If
End Sub 'LoadViewState

Protected Overrides Function SaveViewState() As Object
' If AutoPostBack is set, save the SelectedTab to the view
state for postback scenarios
If _autoPostBack Then
Return _selectedIndex.ToString()
Else
Return MyBase.SaveViewState()
End If
End Function 'SaveViewState

#Region "Overriden methods"

Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)

'this script is client script and should appear only once
If Not Page.IsClientScriptBlockRegistered("TabControl_vbs")
Then
Dim reader As New
System.IO.StreamReader(Me.GetType().Assembly.GetManifestResourceStream(Me.GetType(),
"TabControl.vbs"))
Dim script As String = "<script language='vbscript'
type='text/vbscript' >" _
+ ControlChars.CrLf _
+ "<!--" _
+ ControlChars.CrLf _
+ reader.ReadToEnd() _
+ ControlChars.CrLf _
+ "//-->" _
+ ControlChars.CrLf _
+ "</script>"
Page.RegisterClientScriptBlock("TabControl_vbs", script)

reader = Nothing
script = Nothing
End If

End Sub 'OnPreRender

Private Function GetSelectedIndexForRender() As Integer

If Tabs.Count > 0 Then
' Get the Selected Index.
' For a non-AutoPostBack TabControl, the selected index
' is stored in a cookie.
' Otherwise, it is stored as a property of the TabControl.
If Not _autoPostBack And Not (Page Is Nothing) Then
_selectedIndex = 0
Dim cookie As System.Web.HttpCookie =
Page.Request.Cookies((Me.UniqueID + "_SelectedIndex"))
If Not (cookie Is Nothing) Then
_selectedIndex = Int32.Parse(cookie.Value)
End If
If _selectedIndex < 0 Or _selectedIndex > Tabs.Count -
1 Then
_selectedIndex = 0
End If
End If

'if the selected tab isn't enabled, it can't be selected
If Tabs(_selectedIndex).Enabled Then
Return _selectedIndex
Else
_selectedIndex = -1
'get the first tab that's enabled and select it
For Each myTab As Tab In Tabs
If myTab.Enabled Then
Return Tabs.IndexOf(myTab)
Exit For
End If
Next
End If
End If

End Function 'GetSelectedIndexForRender

Private Sub GetTabFormatValuesForRender()

Dim _tabCount As Integer = Tabs.Count

'get the number of tabs in full rows and their widths
_tabsInFullRow = TabsPerRow
_fullRowTabWidth = Unit.Pixel(Math.Floor(Width.Value /
CDbl(_tabsInFullRow)))

'get the number of rows, total
_tabRows = CType(Math.Ceiling(CDbl(_tabCount) /
CDbl(_tabsInFullRow)), Integer)

'get the number of tabs in a partial row (a row with fewer than
TabsPerRow tabs)
If _tabRows * _tabsInFullRow = _tabCount Then
_fullRows = _tabRows
Else
_fullRows = _tabRows - 1
End If
_tabsInPartRow = _tabCount - (_fullRows * _tabsInFullRow)

'get the widths of tabs in a partial row
If _tabsInPartRow > 0 Then
_partRowTabWidth = Unit.Pixel(Math.Floor(Width.Value /
CDbl(_tabsInPartRow)))
Else
_partRowTabWidth = _fullRowTabWidth
End If

'but just in case they don't divide roundly, we need the
remainders
_fullRowRemainder = Width.Value - _fullRowTabWidth.Value *
_tabsInFullRow
_partRowRemainder = Width.Value - _partRowTabWidth.Value *
_tabsInPartRow

'figure out the height of the masterPage
_tabPageHeight = Unit.Pixel(Height.Value - (_tabRows *
TabHeight.Value))

'let's make a jagged array that represents the tabs in their
rows
'we'll put the tab widths in Pair.Second
ReDim _rowArray(_tabRows - 1)
For i As Integer = 0 To _tabRows - 1
If _fullRows < _tabRows And i = 0 Then
ReDim _rowArray(i)(_tabsInPartRow - 1)
For j As Integer = 0 To _tabsInPartRow - 1
If j = 0 Then
'add in the remainder
_rowArray(i)(j) = New Pair(-5,
Unit.Pixel(_partRowTabWidth.Value + _partRowRemainder))
Else
_rowArray(i)(j) = New Pair(-4,
_partRowTabWidth)
End If
Next
Else
ReDim _rowArray(i)(_tabsInFullRow - 1)
For j As Integer = 0 To _tabsInFullRow - 1
If j = 0 Then
'add in the remainder
_rowArray(i)(j) = New Pair(-3,
Unit.Pixel(_fullRowTabWidth.Value + _fullRowRemainder))
Else
_rowArray(i)(j) = New Pair(-2,
_fullRowTabWidth)
End If
Next
End If
Next

'now let's fill that array with tab indices (that goes into
Pair.First)
Dim _tabCollectionCounter As Integer = 0
Dim _tabCounter As Integer = 0
Dim _rowCounter As Integer = _tabRows - 1

_tabCount = Tabs.Count

Do While _tabCollectionCounter < _tabCount
_rowArray(_rowCounter)(_tabCounter).First =
_tabCollectionCounter
If _tabCollectionCounter = _selectedIndex Then
_selectedRow = _rowCounter
End If
_tabCounter = _tabCounter + 1
If _tabCounter = _tabsInFullRow Then
_rowCounter = _rowCounter - 1
_tabCounter = 0
End If

_tabCollectionCounter = _tabCollectionCounter + 1
Loop

End Sub 'GetTabFormatValuesForRender

Private Sub ApplyChildPostBack()

'Populate controls with PostData, saving a list of those that
were modified:
Dim IsChanged As Boolean
Dim requestForm As New
System.Collections.Specialized.NameValueCollection(Page.Request.Form)
Dim propertyChangedList As String = requestForm(Me.ClientID &
":propertyChangedList")
If propertyChangedList Is Nothing Then
Exit Sub
End If

Dim changedControls() As String =
propertyChangedList.Split(",")
Dim modifiedControls As New ArrayList
For Each myTab As Tab In Tabs
For Each myControl As Control In myTab.Controls
If TypeOf myControl Is IPostBackDataHandler Then
'If a property has changed on a control, update it
IsChanged = False
For i As Integer = 0 To changedControls.Length - 1
If changedControls(i) = myControl.ID Then
IsChanged = True
Exit For
End If
Next
If IsChanged Then
If CType(myControl,
IPostBackDataHandler).LoadPostData(myControl.ID, requestForm) Then
modifiedControls.Add(myControl)
End If
End If
End If
Next myControl
Next myTab

'Raise PostDataChanged event on all modified controls:
Dim modifiedControl As IPostBackDataHandler
For Each modifiedControl In modifiedControls
modifiedControl.RaisePostDataChangedEvent()
Next modifiedControl

End Sub 'ApplyChildPostBack

Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()
_propertyChangedList = New DropDownList
_propertyChangedList.ID = "PropertyChangedList"
_propertyChangedList.Attributes.Add("style", "display:none")
Controls.Add(_propertyChangedList)
End Sub 'CreateChildControls

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)

'if there is no usable selectedindex, don't render the control
If GetSelectedIndexForRender() = -1 Then
Exit Sub
End If

'get the arrangement and width of tabs
GetTabFormatValuesForRender()

'a kludgy thing to get around the fact that the contents of
tabs
'aren't seen by the page, and therefore aren't updated
ApplyChildPostBack()

'now let's do the rendering
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0",
False)
writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0",
False)
writer.AddAttribute(HtmlTextWriterAttribute.Border, "0", False)
writer.AddAttribute(HtmlTextWriterAttribute.Width,
Width.ToString, False)
writer.RenderBeginTag(HtmlTextWriterTag.Table)

'first do the rows other than the selected row
For i As Integer = 0 To _rowArray.GetUpperBound(0)
If Not i = _selectedRow Then
writer.RenderBeginTag(HtmlTextWriterTag.Tr)

writer.AddAttribute(HtmlTextWriterAttribute.Nowrap,
"true", False)
writer.AddAttribute(HtmlTextWriterAttribute.Valign,
"middle", False)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

For j As Integer = 0 To _rowArray(i).GetUpperBound(0)
_tabIdx = CInt(_rowArray(i)(j).First)
writer.AddStyleAttribute("border-bottom", "none")
writer.AddStyleAttribute("height",
TabHeight.Value.ToString)
writer.AddStyleAttribute("overflow", "hidden")
writer.AddStyleAttribute("text-align", "center")
writer.AddStyleAttribute("text-align", "center")
writer.AddStyleAttribute("text-align", "center")
writer.AddStyleAttribute("font-family",
TabFontFamily)
writer.AddStyleAttribute("font-size",
TabFontSize.ToString)
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute("padding-top", "3px")
writer.AddStyleAttribute("border-left", "3px
outset")
writer.AddStyleAttribute("border-top", "3px
outset")
writer.AddStyleAttribute("border-right", "3px
outset")
If Tabs(_tabIdx).Enabled Then
writer.AddStyleAttribute("cursor", "hand")
If Not Tabs(_tabIdx).ToolTip.Trim = "" Then
writer.AddAttribute("title",
Tabs(_tabIdx).ToolTip, True)
End If
'set the onclick depending on whether
AutoPostBack is true or not
If _autoPostBack Then

writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "jscript:" +
Page.GetPostBackEventReference(Me, _tabIdx.ToString()), False)
Else

writer.AddAttribute(HtmlTextWriterAttribute.Onclick,
"TabControl_SelectTab(me)", False)
End If
Else
writer.AddAttribute("disabled", "true")
End If
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
CType(_rowArray(i)(j).Second, Unit).ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
Tabs(_tabIdx).ForeColor.Name)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
Tabs(_tabIdx).BackColor.Name)
writer.AddAttribute(HtmlTextWriterAttribute.Name,
Me.ClientID & "_tab_" & _tabIdx.ToString, False)
writer.AddAttribute(HtmlTextWriterAttribute.Id,
Me.ClientID & "_tab_" & _tabIdx.ToString, False)

writer.RenderBeginTag(HtmlTextWriterTag.Div)
writer.Write(Tabs(_tabIdx).Text)
writer.RenderEndTag() 'Div
Next

writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr
End If
Next

'now do the selected row
writer.RenderBeginTag(HtmlTextWriterTag.Tr)

writer.AddAttribute(HtmlTextWriterAttribute.Nowrap, "true",
False)
writer.AddAttribute(HtmlTextWriterAttribute.Valign, "middle",
False)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

For j As Integer = 0 To
_rowArray(_selectedRow).GetUpperBound(0)
_tabIdx = CInt(_rowArray(_selectedRow)(j).First)
If _rowArray(_selectedRow)(j).First = _selectedIndex Then
writer.AddStyleAttribute("border-bottom", "none")
Else
writer.AddStyleAttribute("border-bottom", "3px inset")
End If
writer.AddStyleAttribute("height",
TabHeight.Value.ToString)
writer.AddStyleAttribute("overflow", "hidden")
writer.AddStyleAttribute("text-align", "center")
writer.AddStyleAttribute("font-family", TabFontFamily)
writer.AddStyleAttribute("font-size", TabFontSize.ToString)
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute("padding-top", "3px")
writer.AddStyleAttribute("border-left", "3px outset")
writer.AddStyleAttribute("border-top", "3px outset")
writer.AddStyleAttribute("border-right", "3px outset")
If Tabs(_tabIdx).Enabled Then
writer.AddStyleAttribute("cursor", "hand")
If Not Tabs(_tabIdx).ToolTip.Trim = "" Then
writer.AddAttribute("title", Tabs(_tabIdx).ToolTip,
True)
End If
'set the onclick depending on whether AutoPostBack is
true or not
If _autoPostBack Then

writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "jscript:" +
Page.GetPostBackEventReference(Me, _tabIdx.ToString()), False)
Else

writer.AddAttribute(HtmlTextWriterAttribute.Onclick,
"TabControl_SelectTab(me)", False)
End If
Else
writer.AddAttribute("disabled", "true")
End If
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
CType(_rowArray(_selectedRow)(j).Second, Unit).ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
Tabs(_tabIdx).ForeColor.Name)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
Tabs(_tabIdx).BackColor.Name)
writer.AddAttribute(HtmlTextWriterAttribute.Name,
Me.ClientID & "_tab_" & _tabIdx.ToString, False)
writer.AddAttribute(HtmlTextWriterAttribute.Id, Me.ClientID
& "_tab_" & _tabIdx.ToString, False)
writer.RenderBeginTag(HtmlTextWriterTag.Div)
writer.Write(Tabs(_tabIdx).Text)
writer.RenderEndTag() 'Div
Next

writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr

'so much for the tabs. Now the tab pages/panels
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
Tabs(_selectedIndex).BackColor.Name)
writer.AddStyleAttribute("overflow", "auto")
writer.AddStyleAttribute("border-left", "3px outset")
writer.AddStyleAttribute("border-bottom", "3px outset")
writer.AddStyleAttribute("border-right", "3px outset")
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute(HtmlTextWriterStyle.Height,
_tabPageHeight.ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
Width.ToString)
writer.RenderBeginTag(HtmlTextWriterTag.Div)

For Each myTab As Tab In Tabs
' Only render the TabView under the following conditions:
' (1) AutoPostBack is set to false.
' (2) AutoPostBack is set to true, and the TabView is for
the Selected Tab
If Not _autoPostBack Or (_autoPostBack And _selectedIndex =
_tabs.IndexOf(myTab)) Then
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
myTab.InnerWidth.ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Height,
myTab.InnerHeight.ToString)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
myTab.BackColor.Name)
writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
myTab.ForeColor.Name)
writer.AddStyleAttribute("text-align", "center")
writer.AddAttribute(HtmlTextWriterAttribute.Id,
Me.ClientID & "_panel_" & Tabs.IndexOf(myTab).ToString, False)
writer.AddAttribute(HtmlTextWriterAttribute.Name,
Me.ClientID & "_panel_" & Tabs.IndexOf(myTab).ToString, False)
If _selectedIndex = _tabs.IndexOf(myTab) Then
writer.AddStyleAttribute("display", "inline")
Else
writer.AddStyleAttribute("display", "none")
End If
writer.RenderBeginTag(HtmlTextWriterTag.Div)

If myTab.HasControls() = False Then
myTab.Controls.Add(New LiteralControl("&nbsp;"))
End If

For Each myControl As Control In myTab.Controls
'this is so that we can update property changes on
postback
If TypeOf myControl Is IPostBackDataHandler Then
writer.AddAttribute("onpropertychange",
"TabControl_FlagChange '" & myControl.ClientID & "', '" &
_propertyChangedList.ClientID & "'")
End If
myControl.RenderControl(writer)
Next

writer.RenderEndTag() 'Div
End If
Next

writer.RenderEndTag() 'Div
'this is so that we can update property changes on postback
_propertyChangedList.RenderControl(writer)
writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr
writer.RenderEndTag() 'Table

End Sub 'Render

#End Region

Public Function LoadPostData(ByVal postDataKey As String, ByVal
postCollection As System.Collections.Specialized.NameValueCollection)
As Boolean Implements System.Web.UI.IPostBackDataHandler.LoadPostData
' Stub Implementation, Required for IPostBackDataHandler
' This control must derive from IPostBackDataHandler, even
though it doesn't use its methods.
End Function 'LoadPostData

Public Sub RaisePostDataChangedEvent() Implements
System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent
' Stub Implementation, Required for IPostBackDataHandler
' This control must derive from IPostBackDataHandler, even
though it doesn't use its methods.
End Sub 'RaisePostDataChangedEvent

Public Sub RaisePostBackEvent(ByVal eventArgument As String)
Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
If eventArgument Is Nothing Then
Return
End If
_selectedIndex = Int32.Parse(eventArgument)
Dim e As New EventArgs
OnSelectedIndexChanged(e)
End Sub 'RaisePostBackEvent

Public Event SelectedIndexChanged As EventHandler

Public Overridable Sub OnSelectedIndexChanged(ByVal e As EventArgs)
RaiseEvent SelectedIndexChanged(Me, e)
End Sub 'OnSelectedIndexChanged

Protected Overrides Function OnBubbleEvent(ByVal source As Object,
ByVal args As System.EventArgs) As Boolean
Return False
End Function 'OnBubbleEvent

End Class 'TabControl

<ToolboxItem(False), ParseChildren(False), PersistChildren(True)> _
Public Class Tab
Inherits WebControl

Private _text As String
Private _innerHeight As Unit
Private _innerWidth As Unit
Private _id As String

Public Sub New()
Me.Text = "Tab"
Me.InnerHeight = Unit.Percentage(100)
Me.InnerWidth = Unit.Percentage(100)
Me.Enabled = True
Me.ForeColor = System.Drawing.Color.Black
Me.BackColor = System.Drawing.Color.Silver
End Sub

#Region "Properties"

<Browsable(True), Category("Appearance"), Description("The text
appearing on the tab.")> _
Public Property Text() As String
Get
Return _text
End Get
Set(ByVal Value As String)
_text = Value
End Set
End Property 'Text

<Browsable(True), Category("Appearance"), Description("The height
of the content of the tab panel (can be greater or less than the height
of the panel itself).")> _
Public Property InnerHeight() As Unit
Get
Return _innerHeight
End Get
Set(ByVal Value As Unit)
_innerHeight = Value
End Set
End Property 'InnerHeight

<Browsable(True), Category("Appearance"), Description("The width of
the content of the tab panel (can be greater or less than the width of
the panel itself).")> _
Public Property InnerWidth() As Unit
Get
Return _innerWidth
End Get
Set(ByVal Value As Unit)
_innerWidth = Value
End Set
End Property 'InnerWidth

<Browsable(False)> _
Public Overrides Property ID() As String
Get
Return _id
End Get
Set(ByVal Value As String)
_id = Value
End Set
End Property

#End Region

#Region "WebControl Properties to Hide"

<Browsable(False)> _
Public Shadows ReadOnly Property Visible() As Boolean
Get
Return True
End Get
End Property 'Visible

<Browsable(False)> _
Public Shadows ReadOnly Property BorderColor() As
System.Drawing.Color
Get
Return System.Drawing.Color.Empty
End Get
End Property 'BorderColor

<Browsable(False)> _
Public Shadows ReadOnly Property BorderStyle() As BorderStyle
Get
Return Nothing
End Get
End Property 'BorderStyle

<Browsable(False)> _
Public Shadows ReadOnly Property BorderWidth() As Unit
Get
Return Nothing
End Get
End Property 'BorderWidth

<Browsable(False)> _
Public Shadows ReadOnly Property CssClass() As String
Get
Return String.Empty
End Get
End Property 'CssClass

<Browsable(False)> _
Public Shadows ReadOnly Property Font() As System.Drawing.Font
Get
Return Nothing
End Get
End Property 'Font

<Browsable(False)> _
Public Shadows ReadOnly Property Height() As Unit
Get
Return Unit.Empty
End Get
End Property 'Height

<Browsable(False)> _
Public Shadows ReadOnly Property Width() As Unit
Get
Return Unit.Empty
End Get
End Property 'Width

<Browsable(False)> _
Public Shadows ReadOnly Property EnableViewState() As Boolean
Get
Return True
End Get
End Property 'EnableViewState

<Browsable(False)> _
Public Shadows ReadOnly Property AccessKey() As String
Get
Return String.Empty
End Get
End Property 'AccessKey

#End Region

Protected Overrides Function OnBubbleEvent(ByVal source As Object,
ByVal args As System.EventArgs) As Boolean
Return False
End Function 'OnBubbleEvent

End Class 'Tab

Public Class TabCollection
Inherits CollectionBase

Default Public ReadOnly Property Item(ByVal index As Integer) As
Tab
Get
If index < 0 Or index >= MyBase.List.Count Then
Stop
End If
Return CType(MyBase.List(index), Tab)
End Get
End Property 'Item

Public Sub Add(ByVal myTab As Tab)
MyBase.List.Add(myTab)
End Sub 'Add

Public Function IndexOf(ByVal myTab As Tab) As Integer
Return MyBase.List.IndexOf(myTab)
End Function 'IndexOf

End Class 'TabCollection

Public Class TabControlDesigner
Inherits System.Web.UI.Design.ControlDesigner

Private verbAddTab As DesignerVerb
Private verbShowNextTab As DesignerVerb
Private verbRemoveTab As DesignerVerb
Private DesignTimeSelectedIndex As Integer

Public Sub New()
verbAddTab = New DesignerVerb("Add New Tab", New
EventHandler(AddressOf AddTab))
verbShowNextTab = New DesignerVerb("Show Next Tab", New
EventHandler(AddressOf ShowNextTab))
verbRemoveTab = New DesignerVerb("Remove Current Tab", New
EventHandler(AddressOf RemoveTab))
MyBase.Verbs.Add(verbAddTab)
MyBase.Verbs.Add(verbShowNextTab)
MyBase.Verbs.Add(verbRemoveTab)
End Sub 'New

Public Overrides Sub Initialize(ByVal component As IComponent)
MyBase.Initialize(component)
Dim tabControl As tabControl = CType(component, tabControl)
DesignTimeSelectedIndex = tabControl.SelectedIndex
Dim ss As ISelectionService =
CType(GetService(GetType(ISelectionService)), ISelectionService)
Dim ccs As IComponentChangeService =
CType(GetService(GetType(IComponentChangeService)),
IComponentChangeService)
If Not (ss Is Nothing) Then
AddHandler ss.SelectionChanged, AddressOf
OnSelectionChanged
AddHandler ccs.ComponentChanged, AddressOf
OnComponentChanged
End If
End Sub 'Initialize

Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
Dim ss As ISelectionService =
CType(GetService(GetType(ISelectionService)), ISelectionService)
Dim ccs As IComponentChangeService =
CType(GetService(GetType(IComponentChangeService)),
IComponentChangeService)
If Not (ss Is Nothing) Then
AddHandler ss.SelectionChanged, New EventHandler(AddressOf
OnSelectionChanged)
AddHandler ccs.ComponentChanged, New
ComponentChangedEventHandler(AddressOf OnComponentChanged)
End If
MyBase.Dispose(disposing)
End Sub 'Dispose

Public Overrides Sub OnComponentChanged(ByVal sender As Object,
ByVal e As ComponentChangedEventArgs)
MyBase.OnComponentChanged(sender, e)
If e.Component Is Me.Component Then
ModifyMenu()
End If
End Sub 'OnComponentChanged

Public Overrides ReadOnly Property
DesignTimeHtmlRequiresLoadComplete() As Boolean
Get
Return True
End Get
End Property 'DesignTimeHtmlRequiresLoadComplete

Protected Overrides Function GetEmptyDesignTimeHtml() As String
' Provide the developer with info on how to add tabs to the
TabControl.
Dim strHtml As String = ""
strHtml += "<table style='font-family: Tahoma; font-size: 8pt;
color:buttontext; background-color:buttonface; border: solid 1px
border-top-color: buttonhighlight; border-left-color: buttonhightlight;
border-right-color: buttonshadow; borderbottom-color: buttonshadow;
display: inline'>"
strHtml += "<tr><td><b>TabControl</b> - " + Me.ID +
"</td></tr>"
strHtml += "<tr><td>Please add Tabs through the Tabs
(Collection) property in the Properties pane,</td></tr>"
strHtml += "<tr><td>or by clicking ""Add New Tab"" in either
the description area of the</td></tr>"
strHtml += "<tr><td>Properties pane or the right-click
menu.</td></tr>"
strHtml += "<tr><td>Then switch to HTML view and edit each
Tab's view by inserting inner content.</td></tr></table>"
Return strHtml
End Function 'GetEmptyDesignTimeHtml

Public Overrides Function GetDesignTimeHtml() As String

Dim tabControl As tabControl = CType(Me.Component, tabControl)
If Not (tabControl Is Nothing) And tabControl.Tabs.Count > 0
Then
Dim stringWriter As New stringWriter
Dim writer As New HtmlTextWriter(stringWriter)

Dim _tabRows As Integer
Dim _fullRows As Integer
Dim _tabsInFullRow As Integer = tabControl.TabsPerRow
Dim _tabsInPartRow As Integer
Dim _partRowTabWidth As Unit
Dim _fullRowTabWidth As Unit
Dim _fullRowRemainder As Integer
Dim _partRowRemainder As Integer
Dim _tabPageHeight As Unit
Dim _rowArray As Pair()()
Dim _tabIdx As Integer
Dim _selectedRow As Integer
Dim _autoPostBack As Boolean = tabControl.AutoPostBack
Dim _tabHeight As Unit = tabControl.TabHeight
Dim _tabFontFamily As String = tabControl.TabFontFamily
Dim _tabFontSize As FontUnit = tabControl.TabFontSize
Dim _width As Unit = tabControl.Width
Dim _height As Unit = tabControl.Height
Dim _tabCount As Integer = tabControl.Tabs.Count

'get the widths of tabs in a full row
_fullRowTabWidth = Unit.Pixel(Math.Floor(_width.Value /
CDbl(_tabsInFullRow)))

'get the number of rows, total
_tabRows = CType(Math.Ceiling(CDbl(_tabCount) /
CDbl(_tabsInFullRow)), Integer)

'get the number of tabs in a partial row (a row with fewer
than TabsPerRow tabs)
If _tabRows * _tabsInFullRow = _tabCount Then
_fullRows = _tabRows
Else
_fullRows = _tabRows - 1
End If
_tabsInPartRow = _tabCount - (_fullRows * _tabsInFullRow)

'get the widths of tabs in a partial row
If _tabsInPartRow > 0 Then
_partRowTabWidth = Unit.Pixel(Math.Floor(_width.Value /
CDbl(_tabsInPartRow)))
Else
_partRowTabWidth = _fullRowTabWidth
End If

'but just in case they don't divide roundly, we need the
remainders
_fullRowRemainder = _width.Value - _fullRowTabWidth.Value *
_tabsInFullRow
_partRowRemainder = _width.Value - _partRowTabWidth.Value *
_tabsInPartRow

'figure out the height of the masterPage
_tabPageHeight = Unit.Pixel(_height.Value - (_tabRows *
_tabHeight.Value))

'let's make a jagged array that represents the tabs in
their rows
'we'll put the tab widths in Pair.Second
ReDim _rowArray(_tabRows - 1)
For i As Integer = 0 To _tabRows - 1
If _fullRows < _tabRows And i = 0 Then
ReDim _rowArray(i)(_tabsInPartRow - 1)
For j As Integer = 0 To _tabsInPartRow - 1
If j = 0 Then
'add in the remainder
_rowArray(i)(j) = New Pair(-1,
Unit.Pixel(_partRowTabWidth.Value + _partRowRemainder))
Else
_rowArray(i)(j) = New Pair(-1,
_partRowTabWidth)
End If
Next
Else
ReDim _rowArray(i)(_tabsInFullRow - 1)
For j As Integer = 0 To _tabsInFullRow - 1
If j = 0 Then
'add in the remainder
_rowArray(i)(j) = New Pair(-1,
Unit.Pixel(_fullRowTabWidth.Value + _fullRowRemainder))
Else
_rowArray(i)(j) = New Pair(-1,
_fullRowTabWidth)
End If
Next
End If
Next

'now let's fill that array with tab indices (that goes into
Pair.First)
Dim _tabCollectionCounter As Integer = 0
Dim _tabCounter As Integer = 0
Dim _rowCounter As Integer = _tabRows - 1

Do While _tabCollectionCounter < _tabCount
_rowArray(_rowCounter)(_tabCounter).First =
_tabCollectionCounter
If _tabCollectionCounter = DesignTimeSelectedIndex Then
_selectedRow = _rowCounter
End If
_tabCounter = _tabCounter + 1
If _tabCounter = _tabsInFullRow Then
_rowCounter = _rowCounter - 1
_tabCounter = 0
End If

_tabCollectionCounter = _tabCollectionCounter + 1
Loop

'now let's do the rendering
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,
"0", False)
writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing,
"0", False)
writer.AddAttribute(HtmlTextWriterAttribute.Border, "0",
False)
writer.AddAttribute(HtmlTextWriterAttribute.Width,
_width.ToString, False)
writer.RenderBeginTag(HtmlTextWriterTag.Table)

'first do all the rows other than the selected row
For i As Integer = 0 To _rowArray.GetUpperBound(0)
If Not i = _selectedRow Then
writer.RenderBeginTag(HtmlTextWriterTag.Tr)

writer.AddAttribute(HtmlTextWriterAttribute.Nowrap,
"true", False)
writer.AddAttribute(HtmlTextWriterAttribute.Valign,
"middle", False)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

For j As Integer = 0 To
_rowArray(i).getUpperBound(0)
_tabIdx = CInt(_rowArray(i)(j).First)
writer.AddStyleAttribute("border-bottom",
"none")
writer.AddStyleAttribute("height",
_tabHeight.Value.ToString)
writer.AddStyleAttribute("overflow", "hidden")
writer.AddStyleAttribute("text-align",
"center")
writer.AddStyleAttribute("font-family",
_tabFontFamily)
writer.AddStyleAttribute("font-size",
_tabFontSize.ToString)
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute("padding-top", "3px")
writer.AddStyleAttribute("border-left", "3px
outset")
writer.AddStyleAttribute("border-top", "3px
outset")
writer.AddStyleAttribute("border-right", "3px
outset")
writer.AddStyleAttribute("cursor", "hand")

writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
CType(_rowArray(i)(j).Second, Unit).ToString)

writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
tabControl.Tabs(_tabIdx).ForeColor.Name)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
tabControl.Tabs(_tabIdx).BackColor.Name)

writer.RenderBeginTag(HtmlTextWriterTag.Div)
writer.Write(tabControl.Tabs(_tabIdx).Text)
writer.RenderEndTag() 'Div
Next

writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr
End If
Next

'then do the selected row
writer.RenderBeginTag(HtmlTextWriterTag.Tr)

writer.AddAttribute(HtmlTextWriterAttribute.Nowrap, "true",
False)
writer.AddAttribute(HtmlTextWriterAttribute.Valign,
"middle", False)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

For j As Integer = 0 To
_rowArray(_selectedRow).GetUpperBound(0)
_tabIdx = CInt(_rowArray(_selectedRow)(j).First)
If _rowArray(_selectedRow)(j).First =
DesignTimeSelectedIndex Then
writer.AddStyleAttribute("border-bottom", "none")
Else
writer.AddStyleAttribute("border-bottom", "3px
inset")
End If
writer.AddStyleAttribute("height",
_tabHeight.Value.ToString)
writer.AddStyleAttribute("overflow", "hidden")
writer.AddStyleAttribute("text-align", "center")
writer.AddStyleAttribute("font-family", _tabFontFamily)
writer.AddStyleAttribute("font-size",
_tabFontSize.ToString)
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute("padding-top", "3px")
writer.AddStyleAttribute("border-left", "3px outset")
writer.AddStyleAttribute("border-top", "3px outset")
writer.AddStyleAttribute("border-right", "3px outset")
writer.AddStyleAttribute("cursor", "hand")
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
CType(_rowArray(_selectedRow)(j).Second, Unit).ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
tabControl.Tabs(_tabIdx).ForeColor.Name)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
tabControl.Tabs(_tabIdx).BackColor.Name)

writer.RenderBeginTag(HtmlTextWriterTag.Div)
writer.Write(tabControl.Tabs(_tabIdx).Text)
writer.RenderEndTag() 'Div
Next

writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr

'so much for the tabs. Now the tab pages/panels
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)


writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
tabControl.Tabs(tabControl.SelectedIndex).BackColor.Name)
writer.AddStyleAttribute("overflow", "auto")
writer.AddStyleAttribute("border-left", "3px outset")
writer.AddStyleAttribute("border-bottom", "3px outset")
writer.AddStyleAttribute("border-right", "3px outset")
writer.AddStyleAttribute("display", "inline")
writer.AddStyleAttribute(HtmlTextWriterStyle.Height,
_tabPageHeight.ToString)
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
_width.ToString)
writer.RenderBeginTag(HtmlTextWriterTag.Div)

For Each myTab As Tab In tabControl.Tabs
' Only render the TabView under the following
conditions:
' (1) AutoPostBack is set to false.
' (2) AutoPostBack is set to true, and the TabView is
for the Selected Tab
If DesignTimeSelectedIndex =
tabControl.Tabs.IndexOf(myTab) Then
writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
myTab.InnerWidth.ToString)

writer.AddStyleAttribute(HtmlTextWriterStyle.Height,
myTab.InnerHeight.ToString)

writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
myTab.BackColor.Name)
writer.AddStyleAttribute(HtmlTextWriterStyle.Color,
myTab.ForeColor.Name)
writer.AddStyleAttribute("text-align", "center")
writer.RenderBeginTag(HtmlTextWriterTag.Div)

If myTab.HasControls() = False Then
myTab.Controls.Add(New
LiteralControl("&nbsp;"))
End If


For Each myControl As Control In myTab.Controls
myControl.RenderControl(writer)
Next

writer.RenderEndTag() 'Div
End If
Next

writer.RenderEndTag() 'Div
writer.RenderEndTag() 'Td
writer.RenderEndTag() 'Tr
writer.RenderEndTag() 'Table

Return stringWriter.ToString()
Else
Return Me.GetEmptyDesignTimeHtml()
End If

End Function 'GetDesignTimeHtml

Private Sub OnSelectionChanged(ByVal sender As Object, ByVal e As
EventArgs)
Dim ss As ISelectionService = CType(sender, ISelectionService)
If Not (ss Is Nothing) Then
Dim bTabControlSelected As Boolean =
ss.GetComponentSelected(Me.Component)
If bTabControlSelected Then
ModifyMenu()
End If
End If
End Sub 'OnSelectionChanged

Private Sub ModifyMenu()
Dim tabControl As tabControl = CType(Me.Component, tabControl)
verbShowNextTab.Visible = False
verbRemoveTab.Visible = False
verbShowNextTab.Visible = tabControl.Tabs.Count > 1
verbRemoveTab.Visible = tabControl.Tabs.Count > 0
End Sub 'ModifyMenu

Private Sub AddTab(ByVal sender As Object, ByVal e As EventArgs)
Dim tabControl As tabControl = CType(Me.Component, tabControl)
Dim myTab As New Tab
tabControl.Tabs.Add(myTab)
tabControl.Controls.Add(myTab)
myTab.Text = "Tab " & tabControl.Tabs.Count.ToString
myTab.ID = myTab.ClientID
DesignTimeSelectedIndex = tabControl.Tabs.Count - 1
OnComponentChanged(Me, New
ComponentChangedEventArgs(tabControl, Nothing, Nothing, Nothing))
End Sub 'AddTab

Private Sub ShowNextTab(ByVal sender As Object, ByVal e As
EventArgs)
Dim tabControl As tabControl = CType(Me.Component, tabControl)
Dim TabCount As Integer = tabControl.Tabs.Count
If TabCount > 0 Then
DesignTimeSelectedIndex = (DesignTimeSelectedIndex + 1) Mod
TabCount
UpdateDesignTimeHtml()
End If
End Sub 'ShowNextTab

Private Sub RemoveTab(ByVal sender As Object, ByVal e As EventArgs)
Dim tabControl As tabControl = CType(Me.Component, tabControl)
If tabControl.Tabs.Count > 0 Then
tabControl.Tabs.RemoveAt(DesignTimeSelectedIndex)
' Ensure the selected index is still valid.
' It is possible that the selected Tab was the last one,
' and that one was removed.
If tabControl.SelectedIndex >= tabControl.Tabs.Count Then
tabControl.SelectedIndex = tabControl.Tabs.Count - 1
If tabControl.SelectedIndex < 0 Then
tabControl.SelectedIndex = 0
End If
End If
' Commit the Change
OnComponentChanged(Me, New
ComponentChangedEventArgs(tabControl, Nothing, Nothing, Nothing))
' Show the closest, right-most sibling Tab in the Designer
DesignTimeSelectedIndex -= 1
If DesignTimeSelectedIndex + 1 >= tabControl.Tabs.Count
Then
DesignTimeSelectedIndex -= 1
End If
ShowNextTab(Me, EventArgs.Empty)
End If
End Sub 'RemoveTab

End Class 'TabControlDesigner
 
B

Brock Allen

It's a bit long, but here it is. I appreciate the help.

Ugg, I should have said "post the smallest amount of code that reproduces
the problem".

Ok, so I skimmed the code and, IIRC, your problem is that declared controls
aren't getting server side events called? I think past of the problem is
that the controls aren't part of the control hierarchy... meaning, I don't
see where the controls that are in the TabdCollection are ever added into
the control tree. If they're not in the control tree then they miss out on
a lot of the server side processing. Again, that was a huge code dump, so
my quick glance at it might be off.
 
L

lisa

Brock said:
Ugg, I should have said "post the smallest amount of code that reproduces
the problem".

I'm sorry. I honestly wasn't sure what part that would be. Although I
suppose I could have left out the designer. said:
Ok, so I skimmed the code and, IIRC, your problem is that declared controls
aren't getting server side events called? I think past of the problem is
that the controls aren't part of the control hierarchy... meaning, I don't
see where the controls that are in the TabdCollection are ever added into
the control tree. If they're not in the control tree then they miss out on
a lot of the server side processing. Again, that was a huge code dump, so
my quick glance at it might be off.

I apologize for the size, Brock. Here is what it looks like in the
HTML at design time:

<fw:TabControl id="TabControl1" runat="server">
<fw:Tab ID="TabControl1__ctl0" Text="Tab 1">&nbsp;</fw:Tab>
<fw:Tab ID="TabControl1__ctl1" Text="Tab 2">
<asp:Button id="Button1" runat="server" Text="Button" />
</fw:Tab>
</fw:TabControl>

When I dragged it onto the form and added two tabs, it looked just like
this, except that there was a non-breaking space where the button is.

When I'm in run time, I see this in the Command Window:

?me.Tabs(1).Controls(1).ID
"Button1"

"Me", in this case, is the TabControl. Maybe I don't understand the
control hierarchy, but doesn't the fact that I can reference the button
at run time this way mean that the button is part of the control
hierarchy?

In terms of how the Tabs themselves are added, the TabCollection has
this:

Public Sub Add(ByVal myTab As Tab)
MyBase.List.Add(myTab)
End Sub 'Add

And the TabControl has this in global declarations:

Private _tabs As New TabCollection

And it has this property:

Public ReadOnly Property Tabs() As TabCollection
Get
Return _tabs
End Get
End Property

Assuming that that's all the relevant code (which I'm unsure of), do
you see what could be causing my problem? Since the Button is already
visible at run time as a child of the second tab, I don't know what I
could add the Button to without it creating a second Button.

The Microsoft Multipage control works the same way. I can add a Button
(let's say) between the start and end tags of a PageView control
(analogous to my Tab control), and somehow, the Button's events are
called properly. The biggest difference I can see is that their
PageViewCollection is derived from ControlCollection, while my
TabCollection is derived from CollectionBase. But I can't see how that
could be causing the problems.

I really appreciate the help, Brock.

Lisa
 
L

lisa

I'm sorry to bother you, but I was wondering if you'd had a chance to
take a look at this.

Thanks,
Lisa
 
B

Brock Allen

Sorry Lisa, I can't quite tell exactly what the problem is from this. What
I'd suggest is to build a small sample outside of your current project that
works the way you want it and then try to compare the differences. Here are
some samples that might get you started:

http://msdn.microsoft.com/library/d...stomizingcontrolswithtemplates.asp?frame=true

http://winfx.msdn.microsoft.com/lib...html/986f63b8-6b50-42b9-a62d-a2f13cafa88b.asp

And more of the same here:

http://samples.gotdotnet.com/quicks.../quickstart/aspplus/doc/webctrlauthoring.aspx
 
L

lisa

Brock, thank you! I didn't find the answer from these links, but they
helped me figure out what the problem was.

I think the fact that the content of the Tabs are children of the Tabs
*is* the problem. If the application sees those controls as children
of the Tabs, and the Tabs as children of the TabControl, there's no way
the app will see the events or postback data of the children unless
it's raised explicitly.

The content of the Tabs needs to be rendered by the TabControl, but it
can't be a part of the TabControl in terms of the control hierarchy.

So now I have a different problem, and maybe it's more easily solved.
On the one hand, I need to be able to access the contents of the Tabs
during Render so that I can render them, but on the other hand, I can't
have them be children of the Tabs. Is there any way in the world that
I can accomplish that?

Thanks again,
Lisa
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top