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 rleblond@jeancoutu.com (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)
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
Don't see what you're looking for? Try a search.
|