'This code is copyright (C) 2005 by HigherMath and Cal Moffett, all rights reserved.

  'It is placed here as a work sample and may not be used for any other purpose.

 

Imports System.ComponentModel

Imports System.Web.UI

Imports System.Web.UI.WebControls

 

Namespace CCXI_Table

 

  'The CCXI Table control has three style sections, one each for the

  'THEAD, TBODY and TFOOT sections of the table. Since they are mostly

  'the same, this class handles the interactions with the property window

  'in the IDE for all three.

 

  'It inherits from the WebControl in order to make use of its intrinsic

  'styles. Some new elements are added and many are turned off.

 

  'ToolboxItem(False) means do not display this control in the IDE's toolbox.

 

  <ToolboxItem(False)> Public Class CCXItableStyle

     Inherits System.Web.UI.WebControls.WebControl

     Implements INamingContainer

 

     Private gobjHorizontalAlign As New HorizontalAlign

     Private gobjVerticalAlign As New VerticalAlign

     Private gstrBackImageUrl As String = ""

 

     'Bindable means that the property can be bound to a database value

     'at runtime.

 

     'Category places the property within a category in the property window

     'if the category is present.

 

     'The Description will show up at the bottom of the propery window if this

     'property is selected.

 

     'NotifyParent enables the parent control to redraw when the property

     'is changed.

 

     <Bindable(True), NotifyParentProperty(True), Category("Appearance"), Description("The background image of the table.")> _

      Public Property [BackImageUrl]() As String

       Get

          Return gstrBackImageUrl

       End Get

       Set(ByVal Value As String)

          gstrBackImageUrl = Value

       End Set

     End Property

 

     'Setting Browsable to False takes these properties off the list

     'because they are irrelevant. We have to do this because these

     'properties have been inherited from WebControl.

 

     <Browsable(False)> Public Overrides Property AccessKey() As String

       Get

       End Get

       Set(ByVal Value As String)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property ID() As String

       Get

       End Get

       Set(ByVal Value As String)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property BorderColor() As System.Drawing.Color

       Get

       End Get

       Set(ByVal Value As System.Drawing.Color)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property BorderStyle() As System.Web.UI.WebControls.BorderStyle

       Get

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.BorderStyle)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property BorderWidth() As System.Web.UI.WebControls.Unit

       Get

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.Unit)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property Height() As System.Web.UI.WebControls.Unit

       Get

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.Unit)

       End Set

     End Property

 

     <Browsable(False)> Public Overrides Property Width() As System.Web.UI.WebControls.Unit

       Get

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.Unit)

       End Set

     End Property

 

     'Now, let's add some styles that are relevant to tables

 

     <Bindable(True), NotifyParentProperty(True), Category("Misc"), Description("The horizontal alignment of the cell contents within this table section.")> _

       Public Property HorizontalAlign() As System.Web.UI.WebControls.HorizontalAlign

       Get

          Return gobjHorizontalAlign

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.HorizontalAlign)

          gobjHorizontalAlign = Value

       End Set

     End Property

 

     <Bindable(True), NotifyParentProperty(True), Category("Misc"), Description("The vertical alignment of the cell contents within this table section.")> _

       Public Property VerticalAlign() As System.Web.UI.WebControls.VerticalAlign

       Get

          Return gobjVerticalAlign

       End Get

       Set(ByVal Value As System.Web.UI.WebControls.VerticalAlign)

          gobjVerticalAlign = Value

       End Set

     End Property

 

     'Since our control does a much better job than MIcrosoft's table control

     'at displaying its layout at design time, we will notify the designer

     'of these property changes so that the layout can be updated for the user

     'to see.

 

     <NotifyParentProperty(True)> Public Overrides Property BackColor() As System.Drawing.Color

       Get

          Return MyBase.BackColor

       End Get

       Set(ByVal Value As System.Drawing.Color)

          MyBase.BackColor = Value

       End Set

     End Property

 

     <NotifyParentProperty(True)> Public Overrides Property CssClass() As String

       Get

          Return MyBase.CssClass

       End Get

       Set(ByVal Value As String)

          MyBase.CssClass = Value

       End Set

     End Property

 

     <NotifyParentProperty(True)> Public Overrides Property Enabled() As Boolean

       Get

         Return MyBase.Enabled

       End Get

       Set(ByVal Value As Boolean)

          MyBase.Enabled = Value

       End Set

     End Property

 

     <NotifyParentProperty(True)> Public Overrides Property EnableViewState() As Boolean

       Get

          Return MyBase.EnableViewState

       End Get

       Set(ByVal Value As Boolean)

          MyBase.EnableViewState = Value

       End Set

     End Property

 

     <NotifyParentProperty(True)> Public Overrides Property ForeColor() As System.Drawing.Color

       Get

          Return MyBase.ForeColor

       End Get

       Set(ByVal Value As System.Drawing.Color)

          MyBase.ForeColor = Value

       End Set

     End Property

  End Class

 

 

  'The CCXItableElement class handles each of the table parts:

  'TBODY, THEAD and TFOOT. It inherits from the Table control

  'because each table element, in fact, functions as a miniature

  'table.

 

  Friend Class CCXItableElement

     Inherits System.Web.UI.WebControls.Table

     Implements INamingContainer

 

     Public garyFieldNames As New ArrayList

 

     Private gobjTableStyle As New CCXItableStyle

     Private gpropTableTagKey As HtmlTextWriterTag = HtmlTextWriterTag.Tbody

 

     'This is where the table style (above) is attached to each

     'of the table elements.

 

     <NotifyParentProperty(True)> Public ReadOnly Property TableStyle() As CCXItableStyle

       Get

          Return gobjTableStyle

       End Get

     End Property

 

     'When the table element is rendered as HTML, this is the tag that is output.

     'It defaults to TBODY but should be changed when this control is

     'initialized to THEAD or TFOOT if appropriate.

 

     'We cannot change the overridden TagKey property to not be readonly so

     'we must invent our own equivalent property and store the value locally.

     'And we must override the 2 related readonly properties to return our

     'local value.

 

     Public Property TableTagKey() As HtmlTextWriterTag

       Get

          Return gpropTableTagKey

       End Get

       Set(ByVal Value As HtmlTextWriterTag)

          gpropTableTagKey = Value

       End Set

     End Property

 

     Protected Overrides ReadOnly Property TagKey() As HtmlTextWriterTag

       Get

          Return gpropTableTagKey

       End Get

     End Property

 

     Protected Overrides ReadOnly Property TagName() As String

       Get

          Return TagKey.ToString

       End Get

     End Property

 

     'When the control is rendered as HTML either for ASP or for the client-side

     'XML data island, this routine will "gather" all the relevant attributes

     'and styles and output appropriate HTML. For tables, most of these

     'attributes are same when individual cells or rows or the entire table

     'is being rendered. However, there are a few specific to table, row or cell.

     'Thus one of the optional parameters must be supplied for whichever of these

     'entities is being rendered.

 

     Private Sub GatherAttributes(ByVal output As System.Web.UI.HtmlTextWriter, _

       ByVal objControl As System.Web.UI.WebControls.WebControl, _

       Optional ByVal objTableStyle As CCXItableStyle = Nothing, _

       Optional ByVal objTableRow As WebControls.TableRow = Nothing, _

       Optional ByVal objTableCell As WebControls.TableCell = Nothing)

 

       With objControl

          Dim strColor As String = ""

          Dim strFontFamilies As String = Join(.Font.Names, ",")

          Dim strFontSize As String = ""

          Dim strTextDecoration As String = ""

 

          Select Case .Font.Size.Type

            Case FontSize.AsUnit

              strFontSize = .Font.Size.Unit.ToString

            Case FontSize.Large

              strFontSize = "large"

            Case FontSize.Larger

              strFontSize = "larger"

            Case FontSize.Medium

              strFontSize = "medium"

            Case FontSize.Small

              strFontSize = "small"

            Case FontSize.Smaller

              strFontSize = "smaller"

            Case FontSize.XLarge

              strFontSize = "x-large"

            Case FontSize.XSmall

              strFontSize = "x-small"

            Case FontSize.XXLarge

              strFontSize = "xx-large"

            Case FontSize.XXSmall

              strFontSize = "xx-small"

            Case Else

              strFontSize = ""

          End Select

 

          If strFontSize <> "" Then

            output.AddStyleAttribute(HtmlTextWriterStyle.FontSize, strFontSize)

          End If

 

          If .Font.Names.Length > 0 AndAlso strFontFamilies.Length > 0 Then

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, strFontFamilies)

          End If

 

          If .Font.Strikeout Then strTextDecoration &= " line-through"

          If .Font.Overline Then strTextDecoration &= " overline"

          If .Font.Underline Then strTextDecoration &= " underline"

 

          If strTextDecoration <> "" Then

            output.AddStyleAttribute(HtmlTextWriterStyle.TextDecoration, strTextDecoration)

          End If

 

          If .Font.Italic Then

            output.AddStyleAttribute(HtmlTextWriterStyle.FontStyle, "italic")

          End If

 

          If .Font.Bold Then

            output.AddStyleAttribute(HtmlTextWriterStyle.FontWeight, "bold")

          End If

 

          With .ForeColor

            If Not .IsEmpty Then

              strColor = IIf(.IsNamedColor, .Name, _

               "#" & Hex(.R).PadLeft(2, "0") & Hex(.G).PadLeft(2, "0") & Hex(.B).PadLeft(2, "0"))

 

              output.AddStyleAttribute(HtmlTextWriterStyle.Color, strColor)

            End If

          End With

 

          If Not .AccessKey Is Nothing Then

            With .AccessKey

              If .Length > 0 Then

                 output.AddAttribute(HtmlTextWriterAttribute.Accesskey, .ToString)

              End If

            End With

          End If

 

          With .Height

            If Not .IsEmpty Then

              output.AddStyleAttribute(HtmlTextWriterStyle.Height, .ToString)

            End If

         End With

 

          With .Width

            If Not .IsEmpty Then

              output.AddStyleAttribute(HtmlTextWriterStyle.Width, .ToString)

            End If

          End With

 

          With .BackColor

            If Not .IsEmpty Then

              strColor = IIf(.IsNamedColor, .Name, _

               "#" & Hex(.R).PadLeft(2, "0") & Hex(.G).PadLeft(2, "0") & Hex(.B).PadLeft(2, "0"))

 

              output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, strColor)

            End If

          End With

 

          With .BorderColor

            If Not .IsEmpty Then

              strColor = IIf(.IsNamedColor, .Name, _

               "#" & Hex(.R).PadLeft(2, "0") & Hex(.G).PadLeft(2, "0") & Hex(.B).PadLeft(2, "0"))

 

              output.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, strColor)

            End If

          End With

 

          If .BorderStyle <> BorderStyle.NotSet Then

            output.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, .BorderStyle.ToString)

          End If

 

          With .BorderWidth

            If Not .IsEmpty Then

              output.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, .ToString)

            End If

          End With

 

          .CssClass = .CssClass.Trim

 

          If .CssClass.Length > 0 Then

            output.AddAttribute(HtmlTextWriterAttribute.Class, .CssClass)

          End If

 

          .ToolTip = .ToolTip.Trim

 

          If .ToolTip.Length > 0 Then

            output.AddAttribute(HtmlTextWriterAttribute.Title, .ToolTip)

          End If

 

          If .TabIndex > 0 Then

            output.AddAttribute(HtmlTextWriterAttribute.Tabindex, .TabIndex.ToString)

          End If

 

          If Not .Enabled Then

            output.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled")

          End If

       End With

 

       If Not objTableStyle Is Nothing Then

          With objTableStyle

            .BackImageUrl = .BackImageUrl.Trim

 

            If .BackImageUrl.Length > 0 Then

              output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundImage, "url(" & objTableStyle.BackImageUrl & ")")

            End If

 

            With .HorizontalAlign

              If objTableStyle.HorizontalAlign = HorizontalAlign.NotSet Then

                 If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Align, .Center.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Align, .ToString)

              End If

            End With

 

            With .VerticalAlign

              If objTableStyle.VerticalAlign = VerticalAlign.NotSet Then

                 If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Valign, .Middle.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Valign, .ToString)

              End If

            End With

          End With

       End If

 

       If Not objTableRow Is Nothing Then

          With objTableRow

            With .HorizontalAlign

              If objTableRow.HorizontalAlign = HorizontalAlign.NotSet Then

                 If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Align, .Center.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Align, .ToString)

              End If

            End With

 

            With .VerticalAlign

              If objTableRow.VerticalAlign = VerticalAlign.NotSet Then

                 If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Valign, .Middle.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Valign, .ToString)

              End If

            End With

          End With

       End If

 

       If Not objTableCell Is Nothing Then

          With objTableCell

            With .HorizontalAlign

              If objTableCell.HorizontalAlign = HorizontalAlign.NotSet Then

                If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Align, .Center.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Align, .ToString)

              End If

            End With

 

            With .VerticalAlign

              If objTableCell.VerticalAlign = VerticalAlign.NotSet Then

                 If Me.TagKey <> HtmlTextWriterTag.Tbody Then

                   output.AddAttribute(HtmlTextWriterAttribute.Valign, .Middle.ToString)

                 End If

              Else

                 output.AddAttribute(HtmlTextWriterAttribute.Valign, .ToString)

              End If

            End With

          End With

       End If

 

     End Sub

 

     'Override the HTML rendering to gather up our control-specific attributes

     'and add them to the output.

 

     Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)

 

       GatherAttributes(output, gobjTableStyle, gobjTableStyle)

 

       MyBase.Render(output)

 

     End Sub

 

     'Because tables are created dynamically (and not via straight HTML) on

     'the client side, we must pass to the client-side table creation routines

     'each of the attributes and their values as separate XML entries. This

     'routine handles parsing the attributes as they are rendered in HTML and

     'reformatting them for output to the XML data island. This is called for

     'both template rows and cells.

 

     Private Sub ParseAttributes(ByVal outHtml As HtmlTextWriter, ByVal strHtml As String, ByVal strTag As String)

 

       Dim arySplit() As String

       Dim arySplit2() As String

       Dim colAttrs As New ArrayList

       Dim colValues As New ArrayList

       Dim i As Integer

       Dim j As Integer

       Dim strValue As String

 

       If strHtml = "" Then Exit Sub

 

       arySplit = strHtml.Split("=")

 

       i = 0

 

       While i < UBound(arySplit)

          arySplit2 = arySplit(i).Split(" ")

 

          colAttrs.Add(arySplit2(UBound(arySplit2)))

 

          strValue = ""

 

          arySplit2 = arySplit(i + 1).Split("""")

 

          If arySplit2.Length > 2 Then

            strValue = arySplit2(1)

          End If

 

          colValues.Add(strValue)

 

          i += 1

       End While

 

       For i = 0 To colAttrs.Count - 1

          With outHtml

            .WriteBeginTag(strTag)

            .WriteAttribute("attr", colAttrs(i))

            .WriteAttribute("value", colValues(i))

            .Write(.SelfClosingChars)

            .Write(.TagRightChar)

            .WriteLine()

          End With

       Next

 

     End Sub

 

     'When the control is rendered in ASP, the rows displayed in the designer

     'are the alternating templates. Since the template information is output

     'to a separate XML data island, we must hide them from the renderer then

     'redisplay them after rendering.

 

     Public Sub HideRows(ByVal bHide As Boolean)

 

       Dim i As Integer

 

       For i = 0 To Me.Rows.Count - 1

          Me.Rows(i).Visible = Not bHide

       Next

 

     End Sub

 

     'One of the beauties of this control over the MS Table control

     'is that it supports embedded HTML in the client-side data items.

     'To keep them from prematurely rendering (and messing up the

     'browser's parse), we need to replace "<", ">" and "&" with

     'HTML "entities".

 

     Public Shared Function FilterInnerText(ByVal strText As String) As String

 

       Dim aryParse() As String = strText.Split("&")

       Dim i As Integer

       Dim strOut As String = ""

 

       For i = 0 To aryParse.Length - 1

          If i > 0 Then

            Dim strAdd As String = "&amp;"

 

            If aryParse(i).Length > 2 Then

              If aryParse(i).Substring(0, 3) = "lt;" OrElse _

               aryParse(i).Substring(0, 3) = "gt;" Then

                 strAdd = "&"

              End If

            End If

 

            If aryParse(i).Length > 3 Then

              If aryParse(i).Substring(0, 4) = "amp;" Then strAdd = "&"

            End If

 

            strOut &= strAdd

          End If

 

          strOut &= aryParse(i)

       Next

 

       aryParse = strOut.Split("<")

       strOut = ""

 

       For i = 0 To aryParse.Length - 1

          If i > 0 Then strOut &= "&lt;"

          strOut &= aryParse(i)

       Next

 

       aryParse = strOut.Split(">")

       strOut = ""

 

       For i = 0 To aryParse.Length - 1

          If i > 0 Then strOut &= "&gt;"

          strOut &= aryParse(i)

       Next

 

       Return strOut

 

     End Function

 

     'After the control is rendered as a table by the ASP rendering mechanism,

     'we render a separate XML data island with the alternating row templates.

 

     Public Function MakeTemplateIsland(ByVal strTemplateId As String) As String

 

       Dim i As Integer

       Dim iDelim As Integer = 0

       Dim iStart As Integer

       Dim j As Integer

       Dim outString As New System.IO.StringWriter

       Dim outHtml As New HtmlTextWriter(outString, "    ")

 

       With outHtml

          .WriteLine()

          .WriteLine()

 

          .AddAttribute("id", strTemplateId)

          .AddStyleAttribute("visibility", "hidden")

          .AddStyleAttribute("display", "none")

          .RenderBeginTag("xml")

 

          .RenderBeginTag("ccxi_datatemplates")

 

          garyFieldNames.Clear()

 

          For i = 0 To Me.Rows.Count - 1

            .RenderBeginTag("ccxi_datarowtemplate")

            .RenderBeginTag("ccxi_tablerowtemplate")

 

            With Me.Rows(i)

              Dim outCapture As New System.IO.StringWriter

              Dim outCaptureHtml As New HtmlTextWriter(outCapture)

 

              GatherAttributes(outCaptureHtml, Me.Rows(i), , Me.Rows(i))

              outCaptureHtml.RenderBeginTag("ccxi")

              ParseAttributes(outHtml, outCapture.ToString, "ccxi_rowattr")

 

              For j = 0 To .Cells.Count - 1

                 Dim strCell As String = Me.Rows(i).Cells(j).Text

 

                 outHtml.RenderBeginTag("ccxi_celltemplate")

 

                 outCapture.Close()

                 outCaptureHtml.Close()

 

                 outCapture = New System.IO.StringWriter

                 outCaptureHtml = New HtmlTextWriter(outCapture)

 

                 GatherAttributes(outCaptureHtml, .Cells(j), , , .Cells(j))

                 outCaptureHtml.RenderBeginTag("ccxi")

                 ParseAttributes(outHtml, outCapture.ToString, "ccxi_cellattr")

 

                 outHtml.RenderBeginTag("ccxi_celldata")

                 outHtml.Write(FilterInnerText(strCell))

 

                 iDelim = 0

 

                 Do

                   iDelim = strCell.IndexOf("%%", iDelim)

 

                   If iDelim >= 0 AndAlso iDelim + 2 < strCell.Length Then

                     iStart = iDelim + 2

 

                     iDelim = strCell.IndexOf("%%", iStart)

 

                     If iDelim >= 0 Then

                        Dim strFieldName As String = strCell.Substring(iStart, iDelim - iStart)

 

                        If Not garyFieldNames.Contains(strFieldName) Then

                          garyFieldNames.Add(strFieldName)

                        End If

 

                        iDelim += 2

                     End If

                   End If

                 Loop While iDelim >= 0 AndAlso iDelim < strCell.Length

 

                 outHtml.RenderEndTag()                'ccxi_celldata

                 outHtml.RenderEndTag()                'ccxi_celltemplate

              Next

            End With

 

            .RenderEndTag()             'ccxi_tablerowtemplate

            .RenderEndTag()             'ccxi_datarowtemplate

          Next

 

          .RenderEndTag()         'ccxi_datatemplates

          .RenderEndTag()         'xml

          .WriteLine()

       End With

 

       Return outString.ToString

 

     End Function

 

  End Class

 

End Namespace