M
Matt Winward
I've put together a composite control that renders a main menu for a
web site and it has a collection that contains all the menu items. I
can stick it on a page and add items to it and they render fine. But
as soon as I remove an item from the html source and refresh the
design-time, or if I close and reopen the page, I get this error:
'MenuItems' could not be initialized. Details: 'MenuItems' could not
be added to the collection. Details: Object does not match target
type.
I've been on this for hours and I can't work out (a) what exactly this
error means or (b) what I need to change.
If anyone could point me in the right direction I'd be very grateful!
Here's the code I'm using for the composite control:
============================================
[Designer(typeof(MainMenuDesigner))]
[DefaultProperty("MenuItems")]
[ParseChildren(true, "MenuItems")]
[ToolboxData("<{0}:MainMenu runat=\"server\" width=\"988\"></
{0}:MainMenu>")]
public class MainMenu : CompositeControl
{
private string _logoUrl = string.Empty;
private string _logoHref = string.Empty;
private string _logoAlt = string.Empty;
private string _pageTitle = string.Empty;
private string _loginInfo = string.Empty;
private List<MainMenuItem> _menuitems;
public string LogoUrl { get { return _logoUrl; } set { _logoUrl =
value; } }
public string LogoHref { get { return _logoHref; } set { _logoHref
= value; } }
public string LogoAlternateText { get { return _logoAlt; } set
{ _logoAlt = value; } }
public string PageTitle { get { return _pageTitle; } set
{ _pageTitle = value; } }
public string LoginInfo { get { return _loginInfo; } set
{ _loginInfo = value; } }
/// <summary>
/// Gets a list of all the menu items (not including Home or
Login).
/// </summary>
[Category("Behaviour")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public List<MainMenuItem> MenuItems
{
get
{
if (_menuitems == null) _menuitems = new
List<MainMenuItem>();
return _menuitems;
}
}
/// <summary>
/// Adds a menu item. Home and Login will already exist by
default.
/// </summary>
/// <param name="item"></param>
public void AddMenuItem(MainMenuItem item)
{
if (_menuitems == null) _menuitems = new List<MainMenuItem>();
_menuitems.Add(item);
}
/// <summary>
/// Removes all menu items excluding Home and Login.
/// </summary>
public void ClearMenuItems()
{
if (_menuitems == null) _menuitems = new List<MainMenuItem>();
_menuitems.Clear();
}
/// <summary>
/// Removes a specific menu item. Home and Login can not be
removed.
/// </summary>
/// <param name="item"></param>
public void RemoveMenuItem(MainMenuItem item)
{
if (_menuitems != null)
_menuitems.Remove(item);
}
protected override void CreateChildControls()
{
this.Style.Clear();
if (DesignMode)
this.Style.Add("display", "block");
// Clear out all controls.
Controls.Clear();
// Create and build Header controls.
HtmlGenericControl headerdiv = new HtmlGenericControl("div");
headerdiv.Attributes.Add("class", "header");
HtmlGenericControl headercontentdiv = new
HtmlGenericControl("div");
headercontentdiv.Attributes.Add("class", "headercontent");
HtmlGenericControl h1 = new HtmlGenericControl("h1");
h1.InnerHtml = _pageTitle;
HtmlGenericControl h2 = new HtmlGenericControl("h2");
h2.InnerHtml = _loginInfo;
HyperLink logolink = new HyperLink();
logolink.NavigateUrl = _logoHref;
Image logo = new Image();
logo.ImageUrl = _logoUrl;
logo.AlternateText = _logoAlt;
logo.CssClass = "logo";
if (DesignMode)
logo.Style.Add("margin-top", "5px");
headercontentdiv.Controls.Add(h1);
headercontentdiv.Controls.Add(h2);
headerdiv.Controls.Add(headercontentdiv);
logolink.Controls.Add(logo);
headerdiv.Controls.Add(logolink);
// Create and build Main Menu controls.
HtmlGenericControl menucontainerdiv = new
HtmlGenericControl("div");
menucontainerdiv.Attributes.Add("class", "menucontainer");
HtmlGenericControl ulmenu = new HtmlGenericControl("ul");
ulmenu.Attributes.Add("class", "menu");
MainMenuItem home = new MainMenuItem("Home", "#");
ulmenu.Controls.Add(home);
if (_menuitems != null)
{
foreach (MainMenuItem item in _menuitems)
{
if (DesignMode)
ulmenu.Controls.Add(new MainMenuItem(item.DisplayText,
item.NavigateUrl));
else
ulmenu.Controls.Add(item);
}
}
HtmlGenericControl ulloginmenu = new HtmlGenericControl("ul");
ulloginmenu.Attributes.Add("class", "loginmenu");
MainMenuItem login = new MainMenuItem("Login", "#");
ulloginmenu.Controls.Add(login);
menucontainerdiv.Controls.Add(ulmenu);
menucontainerdiv.Controls.Add(ulloginmenu);
// Add to main Controls collection.
Controls.Add(headerdiv);
Controls.Add(menucontainerdiv);
}
}
public class MainMenuDesigner : CompositeControlDesigner
{
public override bool AllowResize { get { return false; } }
}
web site and it has a collection that contains all the menu items. I
can stick it on a page and add items to it and they render fine. But
as soon as I remove an item from the html source and refresh the
design-time, or if I close and reopen the page, I get this error:
'MenuItems' could not be initialized. Details: 'MenuItems' could not
be added to the collection. Details: Object does not match target
type.
I've been on this for hours and I can't work out (a) what exactly this
error means or (b) what I need to change.
If anyone could point me in the right direction I'd be very grateful!
Here's the code I'm using for the composite control:
============================================
[Designer(typeof(MainMenuDesigner))]
[DefaultProperty("MenuItems")]
[ParseChildren(true, "MenuItems")]
[ToolboxData("<{0}:MainMenu runat=\"server\" width=\"988\"></
{0}:MainMenu>")]
public class MainMenu : CompositeControl
{
private string _logoUrl = string.Empty;
private string _logoHref = string.Empty;
private string _logoAlt = string.Empty;
private string _pageTitle = string.Empty;
private string _loginInfo = string.Empty;
private List<MainMenuItem> _menuitems;
public string LogoUrl { get { return _logoUrl; } set { _logoUrl =
value; } }
public string LogoHref { get { return _logoHref; } set { _logoHref
= value; } }
public string LogoAlternateText { get { return _logoAlt; } set
{ _logoAlt = value; } }
public string PageTitle { get { return _pageTitle; } set
{ _pageTitle = value; } }
public string LoginInfo { get { return _loginInfo; } set
{ _loginInfo = value; } }
/// <summary>
/// Gets a list of all the menu items (not including Home or
Login).
/// </summary>
[Category("Behaviour")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public List<MainMenuItem> MenuItems
{
get
{
if (_menuitems == null) _menuitems = new
List<MainMenuItem>();
return _menuitems;
}
}
/// <summary>
/// Adds a menu item. Home and Login will already exist by
default.
/// </summary>
/// <param name="item"></param>
public void AddMenuItem(MainMenuItem item)
{
if (_menuitems == null) _menuitems = new List<MainMenuItem>();
_menuitems.Add(item);
}
/// <summary>
/// Removes all menu items excluding Home and Login.
/// </summary>
public void ClearMenuItems()
{
if (_menuitems == null) _menuitems = new List<MainMenuItem>();
_menuitems.Clear();
}
/// <summary>
/// Removes a specific menu item. Home and Login can not be
removed.
/// </summary>
/// <param name="item"></param>
public void RemoveMenuItem(MainMenuItem item)
{
if (_menuitems != null)
_menuitems.Remove(item);
}
protected override void CreateChildControls()
{
this.Style.Clear();
if (DesignMode)
this.Style.Add("display", "block");
// Clear out all controls.
Controls.Clear();
// Create and build Header controls.
HtmlGenericControl headerdiv = new HtmlGenericControl("div");
headerdiv.Attributes.Add("class", "header");
HtmlGenericControl headercontentdiv = new
HtmlGenericControl("div");
headercontentdiv.Attributes.Add("class", "headercontent");
HtmlGenericControl h1 = new HtmlGenericControl("h1");
h1.InnerHtml = _pageTitle;
HtmlGenericControl h2 = new HtmlGenericControl("h2");
h2.InnerHtml = _loginInfo;
HyperLink logolink = new HyperLink();
logolink.NavigateUrl = _logoHref;
Image logo = new Image();
logo.ImageUrl = _logoUrl;
logo.AlternateText = _logoAlt;
logo.CssClass = "logo";
if (DesignMode)
logo.Style.Add("margin-top", "5px");
headercontentdiv.Controls.Add(h1);
headercontentdiv.Controls.Add(h2);
headerdiv.Controls.Add(headercontentdiv);
logolink.Controls.Add(logo);
headerdiv.Controls.Add(logolink);
// Create and build Main Menu controls.
HtmlGenericControl menucontainerdiv = new
HtmlGenericControl("div");
menucontainerdiv.Attributes.Add("class", "menucontainer");
HtmlGenericControl ulmenu = new HtmlGenericControl("ul");
ulmenu.Attributes.Add("class", "menu");
MainMenuItem home = new MainMenuItem("Home", "#");
ulmenu.Controls.Add(home);
if (_menuitems != null)
{
foreach (MainMenuItem item in _menuitems)
{
if (DesignMode)
ulmenu.Controls.Add(new MainMenuItem(item.DisplayText,
item.NavigateUrl));
else
ulmenu.Controls.Add(item);
}
}
HtmlGenericControl ulloginmenu = new HtmlGenericControl("ul");
ulloginmenu.Attributes.Add("class", "loginmenu");
MainMenuItem login = new MainMenuItem("Login", "#");
ulloginmenu.Controls.Add(login);
menucontainerdiv.Controls.Add(ulmenu);
menucontainerdiv.Controls.Add(ulloginmenu);
// Add to main Controls collection.
Controls.Add(headerdiv);
Controls.Add(menucontainerdiv);
}
}
public class MainMenuDesigner : CompositeControlDesigner
{
public override bool AllowResize { get { return false; } }
}