Click here to Skip to main content
13,046,773 members (40,923 online)
Rate this:
Please Sign up or sign in to vote.

I am creating a website where I would like some neat context menu controls. I have already found some handy code to create the menu (but post 'em if you've got 'em) but I'm looking to create a standard UC for the site. I was hoping to be able to add items to the control in the same way that an HTML select does or even the asp:dropdown does (more likely the latter as the HTML will be produced from the code in the same way).

Is this even possible?
<uc:ContextMenu id="CustomControl">
   <uc:MenuLink Value="blah" Text="blah" Url="\blah" />
   <uc:MenuButton  Value="blah" Text="blah"  önClick="Blah_OnClick" />

And how is it done?
Maybe it's the same as design time attributes in winform user controls?

PS: I haven't really started looking at control attributes yet so please post any useful info on adding these to the control

Thanks in advance ^_^
Posted 13-May-12 22:52pm
Andy Lanng21.4K
Rate this: bad
Please Sign up or sign in to vote.

Solution 1

So What i understood is that you need your user control to have the attributes that you can set from aspx markup.

If you define public properties in your user control then use can use it like attributes from you pages' markup.

Tell me If my understanding is not correct.
Andy Lanng 14-May-12 6:29am
Thanks for your prompt reply ^_^
I do need to have attributes that I can set from aspx markup, so thank you for that.

I also need to be able to add controls (or even just htmlcontrols) to a list of controls as in the code above.

Is that as simple as including public methods with specific names i.e.
private List _menuItems = new List();
public void Add(HtmlControl item)
Once I've cracked this then I can even create my own Item class if I need to, but that's looking too far ahead.

My ambition is to have a control that can be used from the markup language, as well as in c#, just as if it was a standard control. Thanks again ^_^
Rate this: bad
Please Sign up or sign in to vote.

Solution 2

You need to add the following to your enclosing class:

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)
    ContextMenuItem cmitem = ((ContextMenuItem)control);
    if (_subItems == null)
      _subItems = new List<contextmenuitem>();
    List<contextmenuitem> newlist = new List<contextmenuitem>();
    newlist.AddRange(_subItems.AsQueryable().TakeWhile((item, i) => i >= index));
    _subItems = newlist;
  catch (InvalidCastException ice)
    //This is an expected error more several controls which should not be parsed here anyway

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)
  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:
        closeTag = "</button>";
      case Control_Style.Hyperlink:
        closeTag = "";
      case Control_Style.SubMenu:
        closeTag = "";
    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());
    if (_subItems != null && _subItems.Count > 0)
      writer.WriteAttribute("id", currentId);
      foreach (ContextMenuItem cmi in _subItems)
        cmi.Renderhtml(writer, currentId);
    throw new HttpUnhandledException("Menu Items must be either a HtmlControls or a Sub Menu!");

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
Andy Lanng 16-May-12 6:20am
thanks you for your very detailed answer.

I need to get my head around this a bit but I will post any future question I might have

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web02 | 2.8.170713.1 | Last Updated 15 May 2012
Copyright © CodeProject, 1999-2017
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100