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

R

rleblond

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
(e-mail address removed)

(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
 
J

justncase80

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,039
Messages
2,570,376
Members
47,028
Latest member
IsmaelLans

Latest Threads

Top