|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Why don't child control events trigger OnBubbleEvent?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 Post your code, as that will help in determining what's going on.
-Brock DevelopMentor http://staff.develop.com/ballen Show quoteHide quote > 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 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(" ")) 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(" ")) 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 Brock Allen wrote: Show quoteHide quote > Post your code, as that will help in determining what's going on. > > -Brock > DevelopMentor > http://staff.develop.com/ballen > > > > > 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 > 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. -Brock DevelopMentor http://staff.develop.com/ballen Brock Allen wrote:
> > It's a bit long, but here it is. I appreciate the help. I'm sorry. I honestly wasn't sure what part that would be. Although I> > Ugg, I should have said "post the smallest amount of code that reproduces > the problem". suppose I could have left out the designer. <sheepish grin> > Ok, so I skimmed the code and, IIRC, your problem is that declared I apologize for the size, Brock. Here is what it looks like in thecontrols > 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. HTML at design time: <fw:TabControl id="TabControl1" runat="server"> <fw:Tab ID="TabControl1__ctl0" Text="Tab 1"> </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 I'm sorry to bother you, but I was wondering if you'd had a chance to
take a look at this. Thanks, Lisa l***@starways.net wrote: Show quoteHide quote > Brock Allen wrote: > > > 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". > > I'm sorry. I honestly wasn't sure what part that would be. Although I > suppose I could have left out the designer. <sheepish grin> > > > 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"> </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 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/default.asp?url=/library/en-us/cpguide/html/cpconcustomizingcontrolswithtemplates.asp?frame=true http://winfx.msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_aspnetctrlauth/html/986f63b8-6b50-42b9-a62d-a2f13cafa88b.asp And more of the same here: http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=%2fquickstart%2faspplus%2fdoc%2fwebctrlauthoring.aspx -Brock DevelopMentor http://staff.develop.com/ballen Show quoteHide quote > Brock Allen wrote: > >>> 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". >> > I'm sorry. I honestly wasn't sure what part that would be. Although > I suppose I could have left out the designer. <sheepish grin> > >> 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"> </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 > 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 Brock Allen wrote: > Sorry Lisa, I can't quite tell exactly what the problem is from this. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcustomizingcontrolswithtemplates.asp?frame=trueWhat > 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://winfx.msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_aspnetctrlauth/html/986f63b8-6b50-42b9-a62d-a2f13cafa88b.asp> > http://samples.gotdotnet.com/quickstart/aspplus/default.aspx?url=%2fquickstart%2faspplus%2fdoc%2fwebctrlauthoring.aspx> And more of the same here: > > Show quoteHide quote > > -Brock > DevelopMentor > http://staff.develop.com/ballen > > > > > Brock Allen wrote: > > > >>> 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". > >> > > I'm sorry. I honestly wasn't sure what part that would be. Although > > I suppose I could have left out the designer. <sheepish grin> > > > >> 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"> </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 > >
Datalist - Image loads on localhost but not on server
Valid values for properties Distributing OWC11 DropDownList selectedIndexChanged event not firing Datagrid Hyperlink Doubt Validation on dynamic fields Object reference not set to an instance of an object - newpost Programmatically Rotate Datagrid Rows checkboxlist help WebForm's Size |
|||||||||||||||||||||||