You need to add the following to your enclosing class:
[ParseChildren(false)]
[PersistChildren(true)]
public partial class ContextMenu : UserControl
{...}
That will allow you to add items between the opening and closing tags of your UserControl. I have also included those tags on my ContextMenuitem class so that I can add infinite nested submenus
Another overload you may want to use is
protected override void AddedControl(Control control, int index)
{
try
{
ContextMenuItem cmitem = ((ContextMenuItem)control);
if (_subItems == null)
_subItems = new List<contextmenuitem>();
List<contextmenuitem> newlist = new List<contextmenuitem>();
newlist.AddRange(_subItems.AsQueryable().Take(index).ToList());
newlist.Add(cmitem);
newlist.AddRange(_subItems.AsQueryable().TakeWhile((item, i) => i >= index));
_subItems = newlist;
}
catch (InvalidCastException ice)
{
}
}
</contextmenuitem></contextmenuitem></contextmenuitem>
You could perform a check for several different class types or use inheritance, so long as each control has the same properties.
I personally used one item class, overloaded the RenderControl so that it did nothing and wrote the markup in a new RenderHtml that I called from the ContectMenu class' Render control. That way you don't need to worry about the HtmlControl RenderControl being called. Just write it yourself:
public override void RenderControl(HtmlTextWriter writer){}
public void Renderhtml(HtmlTextWriter writer, string previousId, int iteration = 0)
{
writer.WriteFullBeginTag("li");
string currentId = previousId + "_" + iteration.ToString();
if (this.ViewState["ControlStyle"] != null)
{
Control_Style style = (Control_Style)Enum.Parse(typeof(Control_Style), this.ViewState["ControlStyle"].ToString());
string closeTag = string.Empty;
switch (style)
{
case Control_Style.Button:
writer.WriteBeginTag("button");
closeTag = "</button>";
break;
case Control_Style.Hyperlink:
writer.WriteBeginTag("a");
closeTag = "";
break;
case Control_Style.SubMenu:
writer.WriteBeginTag("span");
closeTag = "";
break;
}
foreach (object key in this.ViewState.Keys)
{
if (this.ViewState[key.ToString()] != null && this.ViewState[key.ToString()].ToString().Length > 0)
writer.WriteAttribute(key.ToString(), this.ViewState[key.ToString()].ToString());
}
writer.Write(">");
writer.WriteLine(this.Text);
writer.WriteLine(closeTag);
if (_subItems != null && _subItems.Count > 0)
{
writer.WriteBeginTag("div");
writer.WriteAttribute("id", currentId);
writer.Write(">");
writer.WriteFullBeginTag("ul");
foreach (ContextMenuItem cmi in _subItems)
{
cmi.Renderhtml(writer, currentId);
}
writer.WriteEndTag("ul");
writer.WriteEndTag("div");
}
}
else
throw new HttpUnhandledException("Menu Items must be either a HtmlControls or a Sub Menu!");
writer.WriteEndTag("li");
}
This is prolly overkill but I have also made sure that my submenu divs have distinctive IDs so that I can make the javascript work over each one. I still haven't got that bit working yet but I'll post it if anyone needs it when I'm done :D