Click here to Skip to main content
Click here to Skip to main content

Simple Tree Structure Menu in MVC 4 with Razor Engine

, 21 Feb 2013
Rate this:
Please Sign up or sign in to vote.
Create basic tree structure menu in MVC4

Introduction

This tip demonstrates quick steps to create a tree structure menu in the MVC4 framework.

Using the Code

Create a new project using MVC4 Template. You will notice that Visual Studio will generate sample code which we don't have to worry about at this point of time. Let the code be as is and we will go ahead and start creating new model classes to create our basic menu Structure.

Right click on Model folder and add a new class with name "Menu".

Now, we will add properties to this class which will help us to prepare a 0 level menu.

Menu.cs

public class Menu
{
    public Menu()
    {
        MenuItems = new List<MenuItem>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<MenuItem> MenuItems { get; set; }
}

Create another class for holding Child Menu Item structure.

public class MenuItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ActionName { get; set; }
    public string ControllerName { get; set; }
    public string Url { get; set; }
    public Boolean Disable { get; set; }
    public Boolean HasAccess { get; set; }
    public Menu ParentMenu { get; set; }
}

Note, we have created a navigation property referencing our Menu class. This will let us store the parent Menu associated to the Item.

As we are ready with basic Menu Structure, let's move on and create some Controller Events.

Right click on Controllers folder and Select Add, and Controller. This will open a Wizard and help you create controller Code, and a layout quickly.

  • Controller Name: Menu Controller
  • Template: MVC controller with read/write action and views, using Entity Framework
  • Model Class: Menu (.Models) (In case you don't see the Models appearing for selection in this Drop down, Close this Wizard, build the project, and it should come up)
  • Data Context Class: and Follow the Instruction to have one in place
  • Views: Razor (CHTML)

Go ahead and Click ADD to Generate Controller Code and Default Views For Menu Model.

Visual Studio automatically creates a Folder under VIEWS with name "MENU" and generates default views for maintaining model data, i.e., Create, Delete, Details, Edit and Index.

Now, let's quickly check this in the browser. By default, the solution will load Home\Index View and to navigate to our menu, we will just need to add Menu in from of the URL : <local host>:1077/Menu.

Follow the same steps for Menu Item.

Now once we have the basic code ready for Menu, and Menu Item, let's go ahead and do some manual modifications to change the layout. I like to display the associated Child Menu Items when Menu is selected. To do this, here are some changes we have to do in Menu/Details.cshtml file.

<fieldset>
    <legend><h3>Menu</h3></legend>
    <div class="display-label">
        @Html.DisplayNameFor(model => model.Name) : @Html.DisplayFor
        (model => model.Name) ( @Html.DisplayFor(model => model.Description))
    </div>
    <fieldset>
        @if (Model.MenuItems != null && Model.MenuItems.Count > 0)
        {
            <legend><h3>Menu Items</h3></legend>
            foreach (var item in Model.MenuItems)
            {
            <div style="border: solid 1px #F0F0F0; margin: 2px">
                <div class="comment-author">
                    Text: @item.Name
                </div>
                <div class="comment-message">
                    Disable: @item.Disable
                </div>
                <div class="comment-message">
                    HasAccess: @item.HasAccess
                </div>
                <p>
                    @Html.ActionLink("Edit", "Edit", "MenuItem", 
                    new { parentMenuId = Model.Id, id = item.Id }, null)
                    |
                    @Html.ActionLink("Delete", "Delete", "MenuItem", 
                    new { parentMenuId = Model.Id, id = item.Id }, null)
                </p>
            </div>
            }
        }
    </fieldset>
    <div id="addMenuItem" style="display: inline;">
        <div>
            @Html.ActionLink("Add Menu Item", "Create", "MenuItem", 
            new { parentMenuId = Model.Id }, null)
        </div>
    </div>
</fieldset>

We have changed the layout to show child menu items when each menu is selected. Now the Layout is ready, we have to make sure when we create Menu Item that it is always associated with a record in Menu. Let's make the changes now in MenuItemController.cs file to achieve this.

Change the Create Menu Item Code as shown below:

public ActionResult Create(int parentMenuId)
{
    Menu menu = db.Menus.Single<Menu>(m => m.Id == parentMenuId);
    return View(new MenuItem { ParentMenu = menu });
}
        
[HttpPost]
public ActionResult Create(int parentMenuId, MenuItem menuitem)
{
    if (ModelState.IsValid)
    {
        Menu menu = db.Menus.Single<Menu>(m => m.Id == parentMenuId);
        menuitem.ParentMenu = menu;
        db.MenuItems.Add(menuitem);
        db.SaveChanges();
        return RedirectToAction("Details", "Menu", new { id = parentMenuId });
    }
    return View(menuitem);      
}

If you have noticed, we have changed the definition and added another parameter to the events. This parameter will get Parent Menu ID and the same will be stored along with Menu Item Record.

We are almost done. Now we have the data ready to generate a Tree Structured Menu. Let's make some simple changes to get tree like layout.

Edit HomeController.cs class, and add this one line of code under INDEX().

ViewBag.MIList = db.MenuItems.ToList();

We created an additional ViewBag property and attached MenuItem List to it. Now using this, we have to make further changes in our Shared/_Layout.cshtml page.

<table style = "margin-left : 10px">
<tr>
<td valign = "top">
@if (ViewBag.MList != null)
{
foreach (Demo.Models.Menu m in ViewBag.MList)
{
    <h4>@m.Name</h4>
    <ul>
    @foreach (Demo.Models.MenuItem ml in ViewBag.MIList)
    {
        if (ml.ParentMenu.Id == m.Id && ml.Disable == false )
        {
        <li>
            @Html.ActionLink(
                @ml.Name,
                @ml.ActionName,
                @ml.ControllerName)
                </li>
        }
    }
    </ul>
}
}

</td>
<td style = "width : 60%">
    <section style="height: 550px">
        @RenderBody()
    </section>
</td>
</tr>

</table>

You are ready to go. Press F5 and create some good Menu and Menu Item Data. This data will be shown as Tree Menu on Landing Page.

License

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

About the Author

Harry Panesar
Program Manager
India India
Around 9 Years of IT development experience across various domains like ERP, LMS, Sales, Accounting, Shopping Carts, Web Development, Mobile Web Development and Client Server Applications using Latest MS Technologies like MVC4, WCF, ASP.NET 2-4, C#, Crystal Report, SQL Server and MSBI Tools.
I am working as a Technical Lead/Project Manager in one of the leading Hyderabad based IT Company.

Comments and Discussions

 
QuestionHow to create submenu dynamically in mvc razor without asp.net PinmemberMember 102220382-Dec-13 18:22 
Questionneed to add PinmemberÖmer Demir14-Oct-13 8:17 
Questionmissing Code PinmemberÖmer Demir14-Oct-13 8:16 
GeneralMy vote of 3 PinmemberMember 99934349-Jun-13 20:12 
Questionyes but Pinmemberzpaulo_carraca24-Apr-13 11:21 
QuestionMissing code PinmemberAndy Van Langendonck20-Feb-13 21:42 
AnswerRe: Missing code PinmemberHarry Panesar21-Feb-13 0:23 
GeneralRe: Missing code [modified] PinmemberAndy Van Langendonck10-Mar-13 9:28 
GeneralRe: Missing code PinmemberHarry Panesar12-Mar-13 6:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 21 Feb 2013
Article Copyright 2013 by Harry Panesar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid