By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,084 Members | 1,969 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,084 IT Pros & Developers. It's quick & easy.

WebControl Problem - Persistance? (Cross-Post)

P: n/a
Hello everyone! I'm having a problem with a WebControl that I'm designing
for a Menu. I've been at it for about 3 weeks now, and can't seem to get
around this problem. So I'm hoping that someone can help me ...

My environment: VS 2003 v7.1.3088, Win2K v5.0.2195 SP3, IE6 v6.0.2800.1106
browser.

I have a class (C3Menu) derived from WebControl, with a property (MenuItems)
that is a collection of menu items. The collection property is defined as a
class which inherits from CollectionBase. I also have a Designer associated
to the C3Menu class which allows design-time support.
See the code below for more details.

The control is generating properly - the menu items are being persisted to
the HTML view, and the control is rendering ok in both design view and at
run-time. An ellipse button appears next to the MenuItems collection, which
allows me to add / remove items from the collection via the standard
collection editor - everything seems normal!

The problem is when I use the following sequence of events:
1) I run my test application to bring the page up in IE6, everything looks
ok.
2) I close the page to return back to the VS editor.
3) I single-click my control to display the properties in the property
browser.
4) I click the ellipses button to edit the menuitems collection.
5) I click Add to add a new item to the collection - I see the item added in
the left pane of the collection editor.
6) I click Ok to return to VS view.
7) The item(s) I just added do not persist to the HTML view, nor to the
design view!

It gets better! If I click to the HTML view and back to the Design view,
the design view gets updated with the new items - but if I click back to the
HTML view, the items are still not persisted! If I go through the above
sequence of events again (immediately after the HTML/Design view switch), I
still see my new items I added - and when I add another item (via collection
editor) and select Ok to return to design view it updates it with ALL my new
items I added and the items are persisted in the HTML view!

It gets even weirder! I can go through the above sequence of events, but if
I select another web control between steps 2 and 3 (a Label for instance)
everything is persisted correctly.

I originally wrote my own custom collection editor and was having the same
problem, so I decided just to utilize the standard collectioneditor - with
the same results. After all of the reading I've done, I'm thinking it has
something to do with a TypeConverter but am not for sure. I added the type
converter on the MenuItem (collection item) definition, but it did not seem
to help.

Any ideas? I would be happy to send the code for anyone to look at, as this
is more of a learning experience for me than anything. This is my first
design-time control writing attempt - any help would be appreciated.

Thanks,

Todd Lucas
email: Todd.Lucas -at- cox.net

Code snippets:
----------------------------------------------------------------------------
-
C3Menu.vb - C3Menu Class Definition
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Web.UI
Imports System.Collections.Specialized
Imports System.Web.UI.WebControls.CommandEventArgs
Imports System.Web.UI.WebControls
Imports System.Drawing
Imports System.Drawing.Design

Namespace C3WebControls

<DefaultProperty("MenuItems"), DefaultEvent("ItemClick"), _
Description("Server Control - Menu Definition."), _
ParseChildren(True), PersistChildren(False), _
Designer(GetType(C3WebControls.C3Menu_Designer)), _
ToolboxData("<{0}:C3Menu runat=server></{0}:C3Menu>")> _
Public Class C3Menu : Inherits System.Web.UI.WebControls.WebControl
....
' Menu items storage:
Dim _menuitems As New C3MenuItems
....
<Bindable(False), Category("Menu Properties"), NotifyParentProperty(True),
_
DesignerSerializationVisibility(DesignerSerializat ionVisibility.Content),
_
PersistenceMode(PersistenceMode.InnerProperty), _
Editor(GetType(C3WebControls.C3MenuItem_Collection Editor),
GetType(UITypeEditor)), _
Description("Collection of Menu Items this object will display.")> _
Public ReadOnly Property [MenuItems]() As C3MenuItems
Get
Return _menuitems
End Get
'This property has no SET value!
End Property
....
----------------------------------------------------------------------------
-
C3MenuItems.vb - C3MenuItems Class Definition

Imports System.Web.UI
Imports System.Globalization
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization

Namespace C3WebControls

' Menu Item Collection Class:
<Description("Menu Item Collection Definition.")> _
Public Class C3MenuItems : Inherits CollectionBase

Default Public Property Item(ByVal index As Integer) As C3MenuItem
Get
Return DirectCast(MyBase.List.Item(index), C3MenuItem)
End Get
Set(ByVal value As C3MenuItem)
MyBase.List.Item(index) = value
End Set
End Property

Public Overridable Function Add(ByVal value As C3MenuItem) As Integer
MyBase.List.Add(value)
End Function

Public Overloads Sub Remove(ByVal Index As Integer)

' ensure that the object exists in the collection.
Dim mnuitm As C3MenuItem
mnuitm = CType(Me.InnerList.Item(Index), C3MenuItem)

' remove object to the collection (by index).
If Not mnuitm Is Nothing Then Me.InnerList.Remove(mnuitm)

End Sub

End Class

End Namespace
----------------------------------------------------------------------------
-
C3MenuItem.vb - C3MenuItem Class Definition

Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.CommandEventArgs
Imports System.Drawing.Design
Imports System.Drawing
Imports System.Reflection
Imports System.Globalization
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization

Namespace C3WebControls

<DefaultProperty("Text"), _
TypeConverter(GetType(C3MenuItem_TypeConverter)), _
Description("Menu Item Properties Definition.")> _
Public Class C3MenuItem

<NonSerialized()> _
Public pOwningMenu As C3Menu

' MenuItem property storage:
Dim _align As String = ""
Dim _closeonclick As Boolean = True
Dim _color3dhigh As Color = ColorTranslator.FromHtml("")

.... all properties are 1 of the above type - string, boolean, color.
.... standard Property Get / Set ...

Public Function Clone() As C3MenuItem

Dim BinFormatter As New
System.Runtime.Serialization.Formatters.Binary.Bin aryFormatter
Dim memStream As New System.IO.MemoryStream

' Serialize the memorystream object to this instance of the object.
BinFormatter.AssemblyFormat =
Runtime.Serialization.Formatters.FormatterAssembly Style.Simple
BinFormatter.Serialize(memStream, Me)
memStream.Position = 0

' DeSerialize the memorystream object.
Dim newItm As New C3MenuItem
newItm = CType(BinFormatter.Deserialize(memStream), C3MenuItem)

' return the clone.
Return newItm

End Function

End Class
Friend Class C3MenuItem_TypeConverter : Inherits TypeConverter

Public Overloads Overrides Function CanConvertFrom(ByVal context As
ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
If sourceType Is GetType(InstanceDescriptor) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function

Public Overloads Overrides Function CanConvertTo(ByVal context As
ITypeDescriptorContext, ByVal destType As Type) As Boolean
If destType Is GetType(InstanceDescriptor) Then
Return True
End If
Return MyBase.CanConvertTo(context, destType)
End Function

Public Overloads Overrides Function ConvertTo(ByVal context As
ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object,
ByVal destType As Type) As Object
If destType Is GetType(InstanceDescriptor) Then
Dim ci As ConstructorInfo =
GetType(C3MenuItem).GetConstructor(System.Type.Emp tyTypes)
Return New InstanceDescriptor(ci, Nothing, False)
End If
Return MyBase.ConvertTo(context, culture, value, destType)
End Function

End Class

----------------------------------------------------------------------------
-
C3Menu_Designer.vb - C3Menu Designer Definition

Imports System.Web.UI.Design
Imports System.ComponentModel.Design
Imports System.ComponentModel
Imports System.Drawing.Design

Namespace C3WebControls

' Designer class for the C3Menu control.
Public Class C3Menu_Designer : Inherits ControlDesigner

' Use PreFilterProperties to remove properties from the designer view.
Protected Overloads Overrides Sub PreFilterProperties(ByVal Properties As
System.Collections.IDictionary)

' Invoke base class method:
MyBase.PreFilterProperties(Properties)

' Remove specified properties from design view:
Properties.Remove("AccessKey")
Properties.Remove("Visible")

End Sub

' Returns the html to use to represent an empty control at design time.
Protected Overrides Function GetEmptyDesignTimeHtml() As String

Dim sTxt As String = "No Menu Items Defined"
Return CreatePlaceHolderDesignTimeHtml(sTxt)

End Function

' Returns the html which represents the control at design time.
Public Overrides Function GetDesignTimeHtml() As String

' Invoke base class method.
Dim html As String = MyBase.GetDesignTimeHtml()

' Set reference to current control instance.
Dim mnu As C3Menu = DirectCast(Component, C3Menu)

Dim tblstyle As String
tblstyle &= "width:" & mnu.Width.ToString & "; "
tblstyle &= "height:" & mnu.Height.ToString & "; "

' If no items defined then display this.
If mnu.MenuItems.Count = 0 Then Return html

Dim itm As C3MenuItem
Dim styl As C3MenuStyle
Dim itmstyle As String

' set reference to menustyle object.
styl = DirectCast(mnu.FindControl(mnu.MenuStyle), C3MenuStyle)

' if style was assigned, then use style font.
If Not styl Is Nothing Then
If Len(styl.FontFamily) > 0 Then tblstyle &= "font-family:" &
styl.FontFamily & "; "
If Len(styl.FontSize) > 0 Then tblstyle &= "font-size:" & styl.FontSize
& "; "
If Len(styl.FontWeight) > 0 Then tblstyle &= "font-weight:" &
styl.FontWeight & "; "
End If

' Build a table for menu items.
html = ""
html &= "<table style=" & Chr(34) & tblstyle & Chr(34) & ">" & vbCrLf
If LCase(mnu.Orientation) = "horizontal" Then html &= "<tr>"

' Display menu as defined.
For Each itm In mnu.MenuItems

If Not LCase(mnu.Orientation) = "horizontal" Then html &= "<tr>" &
vbCrLf

html &= "<td>" & itm.Text & "</td>" & vbCrLf
If Not LCase(mnu.Orientation) = "horizontal" Then html &= "</tr>" &
vbCrLf

Next

If LCase(mnu.Orientation) = "horizontal" Then html &= "</tr>"
html &= "</table>"

'System.Windows.Forms.MessageBox.Show("GetDesignTi meHtml - HTML:" &
vbCrLf & vbCrLf & html, "C3Menu_Designer")
Return html

End Function

End Class

End Namespace
----------------------------------------------------------------------------
-
WebForm1.aspx - WebForm HTML View

<cc1:C3Menu id="C3Menu1" style="LEFT: 208px; TOP: 120px" runat="server"
MenuStyle="C3MenuStyle1">
<MenuItems>
<cc1:C3MenuItem Text="Item Text"></cc1:C3MenuItem>
<cc1:C3MenuItem Text="Item Text"></cc1:C3MenuItem>
<cc1:C3MenuItem Text="Item Text"></cc1:C3MenuItem>
<cc1:C3MenuItem Text="Item Text"></cc1:C3MenuItem>
<cc1:C3MenuItem Text="Last"></cc1:C3MenuItem>
</MenuItems>
</cc1:C3Menu>
Nov 18 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.