custom control (with collection) do not render at Design time

Discussion in 'ASP .Net Building Controls' started by rleblond@jeancoutu.com, Sep 26, 2005.

  1. Guest

    Hello,

    I built a custom control... Everithing is working fine...

    EXCEPT... ;-) When I first place the control on the webform at design
    time it showed as an empty control (it's ok), then I add my first
    collection item and it also showed correctly. BUT when I close or run
    the application when it came back to design time (or when I reopen the
    webform) it gave me this error :

    "MyCol could not be initialized"

    And it doesn't render it any more (also I don't have access to any of
    it properties...)

    BUT at run time it's always working fine.

    Any idea why (code below) ? (I searched a lot on the web and in the
    news group and did not find any solution...)

    Thanks a lots !!!

    Robin Leblond


    (Here is the full code, sorry there is no comment, I rewrote this code
    about 5 times...)




    Imports System
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.ComponentModel
    Imports System.Collections
    Imports System.Diagnostics
    Imports System.ComponentModel.Design
    Imports System.Web.UI.Design
    Imports System.Drawing.Design
    Imports System.IO
    Imports System.Text

    Namespace MyControls
    <ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>"), _
    ParseChildren(True, "MyCol"), _
    PersistChildren(False), _
    ControlBuilder(GetType(MyControlBuilder)), _
    Designer(GetType(MyControlDesigner))> _
    Public Class MyControl
    Inherits System.Web.UI.WebControls.WebControl
    Implements INamingContainer

    Private _MyCol As MyControlCollection

    Public Sub New()
    _MyCol = New MyControlCollection

    End Sub

    <PersistenceMode(PersistenceMode.InnerDefaultProperty), _
    NotifyParentProperty(True), _

    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
    _
    EditorAttribute(GetType(MyControlCollectionEditor),
    GetType(System.Drawing.Design.UITypeEditor))> _
    Public ReadOnly Property MyCol() As MyControlCollection
    Get
    Return _MyCol
    End Get
    End Property

    Public Function SupportedControls() As System.Type()
    Dim TpSC() As System.Type =
    {GetType(System.Web.UI.WebControls.Button)}

    Return TpSC
    End Function

    Public Function GetDesignTimeHtml() As String
    Dim FakeControlCol As New
    System.Web.UI.ControlCollection(Me)

    RenderControlColD(FakeControlCol)

    Return GetCollectionHtml(FakeControlCol)

    End Function

    Private Sub RenderControlColD(ByRef FakeControlCol As
    System.Web.UI.ControlCollection)
    Dim i As Integer

    For i = 0 To _MyCol.Count - 1
    FakeControlCol.Add(_MyCol.Item(i))
    Next

    End Sub

    Private Sub RenderControlCol()
    Dim i As Integer

    For i = 0 To _MyCol.Count - 1
    Me.Controls.Add(_MyCol.Item(i))
    Next

    End Sub

    Private Function GetCollectionHtml(ByRef WebControlCol As
    System.Web.UI.ControlCollection) As String
    Dim SW As New StringWriter
    Dim HTW As New HtmlTextWriter(SW)
    Dim WC As System.Web.UI.WebControls.WebControl

    For Each WC In WebControlCol
    WC.RenderControl(HTW)
    Next

    Return SW.ToString
    End Function

    Protected Overrides Sub Render(ByVal output As
    System.Web.UI.HtmlTextWriter)
    If Not Me.Site Is Nothing Then
    If Me.Site.DesignMode Then
    Exit Sub
    End If
    End If

    RenderControlCol()
    MyBase.Render(output)
    End Sub

    End Class

    Public Class MyControlBuilder
    Inherits ControlBuilder

    Public Sub New()
    MyBase.New()
    End Sub

    Public Function SupportedControls() As System.Type()
    Dim TpSC() As System.Type =
    {GetType(System.Web.UI.WebControls.Button)}

    Return TpSC
    End Function

    Public Function GetSupportedType(ByRef SupporttedType() As
    System.Type, ByVal TagName As String) As System.Type
    Dim TT As System.Type
    Dim TpTT As System.Type

    TpTT = Nothing

    For Each TT In SupporttedType

    RXFramework.ErrorManagment.LogManager.LogEvent("c:\cc3.txt", TagName &
    " - " & TT.Name.ToUpper)
    If TagName.ToUpper.IndexOf(TT.Name.ToUpper) >= 0 Then
    TT = TT
    Exit For
    End If
    Next TT

    Return TT
    End Function

    Public Overrides Function GetChildControlType(ByVal tagName As
    String, ByVal attribs As System.Collections.IDictionary) As System.Type

    Return GetSupportedType(SupportedControls(), tagName)
    End Function
    End Class

    Public Class MyControlDesigner
    Inherits ControlDesigner

    Public Sub New()
    MyBase.New()
    End Sub

    Protected Overrides Function GetEmptyDesignTimeHtml() As String
    Return
    CreatePlaceHolderDesignTimeHtml(GetType(Component).ToString() & "
    control.")
    End Function

    Public Overrides ReadOnly Property AssociatedComponents() As
    System.Collections.ICollection
    Get
    If CType(Component, MyControl).MyCol.Count > 0 Then
    Return CType(Component, MyControl).MyCol
    Else
    Return MyBase.AssociatedComponents
    End If
    End Get
    End Property

    Public Overrides Function GetDesignTimeHtml() As String
    Dim TpStr As String

    If CType(Component, MyControl).MyCol.Count > 0 Then
    TpStr = CType(Component, MyControl).GetDesignTimeHtml
    Else
    TpStr = GetEmptyDesignTimeHtml()
    End If

    MyBase.GetDesignTimeHtml()

    Return TpStr
    End Function

    Protected Overrides Function GetErrorDesignTimeHtml(ByVal e As
    System.Exception) As String
    Return CreatePlaceHolderDesignTimeHtml("An error happen")
    End Function

    End Class

    Public Class MyControlCollection
    Inherits System.Collections.CollectionBase

    Public Sub New()
    list.Clear()
    End Sub

    Public Overrides Function ToString() As String
    Return Me.GetType().Name
    End Function

    Public ReadOnly Property IsReadOnly() As Boolean
    Get
    Return False
    End Get
    End Property

    Public Function Item(ByVal Index As Integer) As
    System.Web.UI.WebControls.Button
    Return list.Item(Index)
    End Function

    Public Sub Remove(ByVal Index As Integer)
    list.Remove(Index)
    End Sub

    Public Sub Insert(ByVal Index As Integer, ByRef Value As
    Object)
    list.Insert(Index, Value)
    End Sub

    Public Function Contains(ByRef Value As Object) As Boolean
    Return list.Contains(Value)
    End Function

    Public Function IndexOf(ByRef Value As Object) As Integer
    Return list.IndexOf(Value)
    End Function

    Public ReadOnly Property IsFixedSize() As Boolean
    Get
    Return False
    End Get
    End Property

    Public Function Add(ByRef Obj As
    System.Web.UI.WebControls.Button) As Integer
    Return list.Add(Obj)
    End Function


    Public ReadOnly Property IsSynchronized() As Boolean
    Get
    Return False
    End Get
    End Property

    Public Sub CopyTo(ByVal nArray As System.Array, ByVal Index As
    Integer)
    list.CopyTo(nArray, Index)
    End Sub

    Public ReadOnly Property SyncRoot() As Object
    Get
    Return list.SyncRoot
    End Get
    End Property


    End Class

    Public Class MyControlCollectionEditor
    Inherits CollectionEditor

    Dim _supportedTypes() As System.Type

    Public Sub New(ByVal NType As System.Type)
    MyBase.New(NType)

    ReDim _supportedTypes(0)
    _supportedTypes(0) =
    GetType(System.Web.UI.WebControls.Button)
    End Sub

    Protected Overrides Function CreateNewItemTypes() As
    System.Type()
    Return _supportedTypes
    End Function
    End Class


    End Namespace
    , Sep 26, 2005
    #1
    1. Advertising

  2. justncase80 Guest

    The designer will actually go through all the steps of creating the
    object from scratch and if you haven't initialized the data properly it
    may create some errors that cause it to not render. What I usually do
    is have it generate some dummy data, like insert some fake rows or
    columns just for the desinger so the user can see what it is probably
    going to look like. In your code you have this:

    If Not Me.Site Is Nothing Then
    If Me.Site.DesignMode Then
    Exit Sub
    End If
    End If


    instead of exiting there you might want to clear the control and add in
    the dummy data there. Also instead of doing all those strange rendering
    functions you're doing you might consider building all of the controls
    in CreateChildControls(); and adding them to Me.Controls.Add( );
    collection. This will insure that all of the postbacks are wired up
    correctly for all child controls otherwise you may find that clicking a
    button doesn't actually work properly.

    (You also have to inherit from INamingContainer)

    ~Justin
    justncase80, Sep 27, 2005
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    707
  2. Øyvind Isaksen
    Replies:
    1
    Views:
    941
    Øyvind Isaksen
    May 18, 2007
  3. Replies:
    1
    Views:
    357
    Teemu Keiski
    Jul 2, 2003
  4. Patrick

    Custom asp.net control using collection - Design Time Refresh

    Patrick, Oct 7, 2005, in forum: ASP .Net Building Controls
    Replies:
    3
    Views:
    356
    Patrick
    Oct 13, 2005
  5. Justin
    Replies:
    12
    Views:
    530
    Justin
    Jul 8, 2005
Loading...

Share This Page