Re: Collection disappearing at run time
- From: lisa@xxxxxxxxxxxx
- Date: 2 May 2005 09:21:09 -0700
I figured out what to do to fix my problem, but I don't understand why
it was causing the problem to begin with. I changed the New method for
the Tab so that it doesn't take any arguments. And now it works. Go
figure. I guess I can live with the mystery, so long as the control is
working.
I made some other tweaks, because there were some minor bugs I hadn't
found. If anyone wants a copy of the control, let me know and I'll
either post it or put it up on my site so that you can download it.
Once I'm totally satisfied with it, I think I'm going to add remote
scripting capability, so that it can autopostback without the page
blinking. They deprecated the blink tag, but .NET is still giving us
eyeaches. That's got to go.
Lisa
lisa@xxxxxxxxxxxx wrote:
> I really, really wanted to finish this one without asking anyone for
> help. But I've been beating my head against this thing, and I'm
> getting nowhere.
>
> I wrote a tab control. I cribbed some ideas from the BlueValley one,
> but mostly after I'd finished the main stuff.
>
> It works just great in design time (the opposite of the usual
problem).
> Except that if I try to add any content to any of the tabs in the
HTML
> view, when I go back to design view, the control won't render
anymore.
> The same thing happens if I try adding content to a tab
> programmatically. At least I think. The problem with knowing for
sure
> is that if I try to view a page that has a tab control on it, whether
I
> add content or not, the same thing happens, and I get an error.
>
> When I trace the error, I find that either running the page or adding
> content in HTML view or both causes the tabs collection to evaporate
> into Nothing.
>
> I've tried debugging in every way I can, but I can't figure out
what's
> making the collection not persist. I'm posting the code here. Feel
> free to take it and use it for yourself, if it becomes fixable. But
if
> anyone can tell me what I'm doing wrong, I'd very much appreciate it.
>
> Um... it's IE only. Again. Sorry.
>
> TIA,
> 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
>
> <ToolboxData("<{0}:TabStrip runat=server></{0}:TabStrip>"),
> Designer(GetType(TabStripDesigner)), PersistChildren(False),
> ParseChildren(True, "Tabs"), DefaultProperty("Tabs"),
> DefaultEvent("SelectedIndexChanged")> _
> Public Class TabStrip
> 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 _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 _visibleTabs As Integer
> Private _rowArray As Pair()()
> Private _selectedRow As Integer
> Private _tabIdx As Integer
> Private _firstVisibleTabIdx As Integer = -1
>
> <Category("Behavior"), Description("The collection of tabs."),
>
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
> NotifyParentProperty(True),
> 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),
> NotifyParentProperty(True),
PersistenceMode(PersistenceMode.Attribute)>
> _
> Public Property TabsPerRow() As Integer
> Get
> Return _tabsPerRow
> End Get
> Set(ByVal Value As Integer)
> _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
>
> <DefaultValue(True)> _
> Public Property AutoPostBack() As Boolean
> Get
> Return _autoPostBack
> End Get
> Set(ByVal Value As Boolean)
> _autoPostBack = Value
> End Set
> End Property
>
> 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("TabStrip_vbs")
Then
> Dim reader As New
>
System.IO.StreamReader(Me.GetType().Assembly.GetManifestResourceStream(Me.GetType(),
> "TabStrip.vbs"))
> Dim script As String = "<script language='vbscript'
> type='text/vbscript' >" _
> + ControlChars.CrLf _
> + "<!--" _
> + ControlChars.CrLf _
> + reader.ReadToEnd() _
> + ControlChars.CrLf _
> + "//-->" _
> + ControlChars.CrLf _
> + "</script>"
> Page.RegisterClientScriptBlock("TabStrip_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 > _tabCount -
1
> Then
> _selectedIndex = 0
> End If
> End If
>
> 'if the selected tab isn't visible and enabled, it can't
be
> selected
> If Tabs(_selectedIndex).Visible And
> Tabs(_selectedIndex).Enabled Then
> Return _selectedIndex
> Else
> _selectedIndex = -1
> 'get the first tab that's both visible and enabled
and
> select it
> For Each myTab As Tab In Tabs
> If myTab.Visible And myTab.Enabled Then
> Return Tabs.IndexOf(myTab)
> Exit For
> End If
> Next
> End If
> End If
>
> End Function 'GetSelectedIndexForRender
>
> Private Sub GetTabFormatValuesForRender()
>
> '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(_visibleTabs) /
> CDbl(_tabsInFullRow)), Integer)
>
> 'get the number of tabs in a partial row (a row with fewer
than
> TabsPerRow tabs)
> If _tabRows * _tabsInFullRow = _visibleTabs Then
> _fullRows = _tabRows
> Else
> _fullRows = _tabRows - 1
> End If
> _tabsInPartRow = _visibleTabs - (_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
> If Tabs(_tabCollectionCounter).Visible Then
> _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
> End If
> _tabCollectionCounter = _tabCollectionCounter + 1
> Loop
>
> End Sub 'GetTabFormatValuesForRender
>
> Protected Overrides Sub Render(ByVal writer As
> System.Web.UI.HtmlTextWriter)
>
> 'get the number of visible tabs
> _visibleTabs = 0
> For Each myTab As Tab In Tabs
> If myTab.Visible Then
> _visibleTabs = _visibleTabs + 1
> End If
> Next
>
> 'if there are no visible tabs, don't render the control
> If _visibleTabs = 0 Then
> Exit Sub
> End If
>
> '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()
>
> '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("font-family", "system")
> writer.AddStyleAttribute("font-size", "8pt")
> 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,
> Tabs(_tabIdx).ForeColor.Name)
>
> writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
> Tabs(_tabIdx).BackColor.Name)
> '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,
> "TabStrip_SelectTab(this)", False)
> End If
> writer.AddAttribute(HtmlTextWriterAttribute.Name,
> "tab_" & _tabIdx.ToString, False)
> writer.AddAttribute(HtmlTextWriterAttribute.Id,
> "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", "system")
> writer.AddStyleAttribute("font-size", "8pt")
> 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,
> Tabs(_tabIdx).ForeColor.Name)
>
> writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
> Tabs(_tabIdx).BackColor.Name)
> '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,
> "TabStrip_SelectTab(this)", False)
> End If
> writer.AddAttribute(HtmlTextWriterAttribute.Name, "tab_"
&
> _tabIdx.ToString, False)
> writer.AddAttribute(HtmlTextWriterAttribute.Id, "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
> myControl.RenderControl(writer)
> Next
>
> writer.RenderEndTag() 'Div
> End If
> Next
>
> writer.RenderEndTag() 'Div
> 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
>
> End Class 'TabStrip
>
> <ToolboxItem(False)> _
> Public Class Tab
> Inherits Control
>
> Private _text As String
> Private _innerHeight As Unit
> Private _innerWidth As Unit
> Private _enabled As Boolean
> Private _visible As Boolean
> Private _foreColor As System.Drawing.Color
> Private _backColor As System.Drawing.Color
>
> Public Sub New(Optional ByVal TabText As String = "Tab")
> Me.Text = TabText
> Me.InnerHeight = Unit.Percentage(100)
> Me.InnerWidth = Unit.Percentage(100)
> Me.Enabled = True
> Me.Visible = True
> Me.ForeColor = System.Drawing.Color.Black
> Me.BackColor = System.Drawing.Color.Silver
> End Sub
>
> <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(True), Category("Behavior"), Description("Whether tab
> can be selected and contents accessed in runtime or not.")> _
> Public Property Enabled() As Boolean
> Get
> Return _enabled
> End Get
> Set(ByVal Value As Boolean)
> _enabled = Value
> End Set
> End Property 'Enabled
>
> <Browsable(True), Category("Behavior"), Description("Whether tab
is
> visible at runtime or not.")> _
> Public Overrides Property Visible() As Boolean
> Get
> Return _visible
> End Get
> Set(ByVal Value As Boolean)
> _visible = Value
> End Set
> End Property 'Visible
>
> <Browsable(True), Category("Appearance"), Description("The color
of
> the text appearing on the tab.")> _
> Public Property ForeColor() As System.Drawing.Color
> Get
> Return _foreColor
> End Get
> Set(ByVal Value As System.Drawing.Color)
> _foreColor = Value
> End Set
> End Property 'ForeColor
>
> <Browsable(True), Category("Appearance"), Description("The
> background of the tab.")> _
> Public Property BackColor() As System.Drawing.Color
> Get
> Return _backColor
> End Get
> Set(ByVal Value As System.Drawing.Color)
> _backColor = Value
> End Set
> End Property 'BackColor
>
> End Class 'Tab
>
> Public Class TabCollection
> Inherits CollectionBase
>
> Default Public ReadOnly Property Item(ByVal index As Integer) As
> Tab
> Get
> 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 TabStripDesigner
> 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 tabStrip As tabStrip = CType(component, tabStrip)
> DesignTimeSelectedIndex = tabStrip.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'>"
> strHtml += "<tr><td><b>TabStrip</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 tabStrip As tabStrip = CType(Me.Component, tabStrip)
> If Not (tabStrip Is Nothing) And tabStrip.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 = tabStrip.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 = tabStrip.AutoPostBack
> Dim _tabHeight As Unit = tabStrip.TabHeight
> Dim _width As Unit = tabStrip.Width
> Dim _height As Unit = tabStrip.Height
> Dim _tabCount As Integer = tabStrip.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
> If tabStrip.Tabs(_tabCollectionCounter).Visible Then
> _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
> 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",
> "system")
> writer.AddStyleAttribute("font-size", "8pt")
> 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,
> tabStrip.Tabs(_tabIdx).ForeColor.Name)
>
> writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
> tabStrip.Tabs(_tabIdx).BackColor.Name)
>
> writer.RenderBeginTag(HtmlTextWriterTag.Div)
> writer.Write(tabStrip.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", "system")
> writer.AddStyleAttribute("font-size", "8pt")
> 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,
> tabStrip.Tabs(_tabIdx).ForeColor.Name)
>
> writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
> tabStrip.Tabs(_tabIdx).BackColor.Name)
>
> writer.RenderBeginTag(HtmlTextWriterTag.Div)
> writer.Write(tabStrip.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,
> tabStrip.Tabs(tabStrip.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 tabStrip.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 =
> tabStrip.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 tabStrip As tabStrip = CType(Me.Component, tabStrip)
> verbShowNextTab.Visible = False
> verbRemoveTab.Visible = False
> verbShowNextTab.Visible = tabStrip.Tabs.Count > 1
> verbRemoveTab.Visible = tabStrip.Tabs.Count > 0
> End Sub 'ModifyMenu
>
> Private Sub AddTab(ByVal sender As Object, ByVal e As EventArgs)
> Dim tabStrip As tabStrip = CType(Me.Component, tabStrip)
> Dim myTab As New Tab
> tabStrip.Tabs.Add(myTab)
> tabStrip.Controls.Add(myTab)
> myTab.Text = "Tab " & tabStrip.Tabs.Count.ToString
> myTab.ID = myTab.ClientID
> DesignTimeSelectedIndex = tabStrip.Tabs.Count - 1
> OnComponentChanged(Me, New
ComponentChangedEventArgs(tabStrip,
> Nothing, Nothing, Nothing))
> End Sub 'AddTab
>
> Private Sub ShowNextTab(ByVal sender As Object, ByVal e As
> EventArgs)
> Dim tabStrip As tabStrip = CType(Me.Component, tabStrip)
> Dim TabCount As Integer = tabStrip.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 tabStrip As tabStrip = CType(Me.Component, tabStrip)
> If tabStrip.Tabs.Count > 0 Then
> tabStrip.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 tabStrip.SelectedIndex >= tabStrip.Tabs.Count Then
> tabStrip.SelectedIndex = tabStrip.Tabs.Count - 1
> If tabStrip.SelectedIndex < 0 Then
> tabStrip.SelectedIndex = 0
> End If
> End If
> ' Commit the Change
> OnComponentChanged(Me, New
> ComponentChangedEventArgs(tabStrip, Nothing, Nothing, Nothing))
> ' Show the closest, right-most sibling Tab in the
Designer
> DesignTimeSelectedIndex -= 1
> If DesignTimeSelectedIndex + 1 >= tabStrip.Tabs.Count
Then
> DesignTimeSelectedIndex -= 1
> End If
> ShowNextTab(Me, EventArgs.Empty)
> End If
> End Sub 'RemoveTab
>
> End Class 'TabControlDesigner
.
- Prev by Date: cutome paging+MS Access Database
- Next by Date: ViewState of Contained Controls?
- Previous by thread: cutome paging+MS Access Database
- Next by thread: ViewState of Contained Controls?
- Index(es):
Loading