简体   繁体   中英

Custom ASP.NET menu control

I am working on a custom menu control, partially as a learning exercise, and I am having trouble with Visual Studio's IntelliSense support for it in markup view.

The conventional ASP.NET menu allows you to place an arbitrary depth of <asp:MenuItem/> elements under the <Items>...</Items> element. I'm after the same behaviour for my menu.

Mine unfortunately does not. VS insists on an empty tag:

<hn:AwesomeMenu runat="server" ID="menu">
    <Items />
</hn:AwesomeMenu>

I have used Reflector to dig into the ASP.NET Menu control and its related classes (MenuItem, MenuItemCollection and soforth) and have ensured that my classes have the same interfaces and attributes, so I'm slightly stumped as to where I'm going wrong. Stubs of my classes so far are as follows:

AwesomeMenu.cs

public class AwesomeMenu
    : HierarchicalDataBoundControl,
      IPostBackEventHandler,
      INamingContainer
{
    [PersistenceMode(PersistenceMode.InnerProperty),
     MergableProperty(false),
     DefaultValue(default(string)),
     Browsable(false)]
    public AwesomeCollection Items
    {
        get { ... }
    }
}

AwesomeCollection.cs

public class AwesomeCollection
    : ICollection,
      IEnumerable,
      IStateManager
{ ... }

AwesomeItem.cs

[ParseChildren(true, "Children")]
public class AwesomeItem
    : IStateManager,
      ICloneable
{
    [PersistenceMode(PersistenceMode.InnerDefaultProperty),
     MergableProperty(false)]
    public AwesomeCollection Children
    {
        get { ... }
    }

    public AwesomeItem Parent
    {
        get { ... }
    }
}

Interface implementations are omitted for brevity. Any help would be appreciated.

Thanks largely to a blog post I belatedly discovered ( The ParseChildren PersistChildren and PersistenceMode.InnerProperty ), I was able to wrap my head around the appropriate usage of the aforementioned attributes.

Basically I only required a [ParseChildren(...)] attribute on the menu class itself. A minimal successful implementation of the desired behaviour is as follows:

Menu.cs

[ParseChildren(ChildrenAsProperties = true)]
public class Menu
    : Control
{
    [PersistenceMode(PersistenceMode.InnerProperty),
     Browsable(false)]
    public List<Item> Items { get; set; }
}

Item.cs

[ParseChildren(
    typeof(Item),
    DefaultProperty = "Items",
    ChildrenAsProperties = true)]
public class Item
{
    public string Text { get; set; }

    [Browsable(false)]
    public List<Item> Items { get; set; }
}

My only question is how the ASP.NET menu achieves the same behaviour without the use of this attribute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM