Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#
Tip/Trick

Simple Tree Structure Menu in MVC 4 with Razor Engine

Rate me:
Please Sign up or sign in to vote.
3.33/5 (2 votes)
21 Feb 2013CPOL3 min read 107.1K   11   15
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

C#
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.

C#
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.

HTML
<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:

C#
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().

C#
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.

C#
<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)


Written By
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

 
NewsUsing this Code for Windows authentication Pin
Member 104163844-May-15 2:02
Member 104163844-May-15 2:02 
QuestionNot getting, what should be the table structure for this Pin
Member 1130495629-Apr-15 18:37
Member 1130495629-Apr-15 18:37 
Questiondynamically fill the menu items in layout page by using mvc 4 (razor)with ADO.net with simple example and db also send them Pin
Member 113172325-Jan-15 22:24
Member 113172325-Jan-15 22:24 
QuestionHomeController.cs Pin
Member 110520202-Sep-14 1:44
Member 110520202-Sep-14 1:44 
QuestionData Context Class Pin
Member 110520202-Sep-14 0:47
Member 110520202-Sep-14 0:47 
QuestionHow to create submenu dynamically in mvc razor without asp.net Pin
Member 102220382-Dec-13 18:22
professionalMember 102220382-Dec-13 18:22 
Questionneed to add Pin
Ömer Demir14-Oct-13 8:17
Ömer Demir14-Oct-13 8:17 
AnswerRe: need to add Pin
Robowski16-Mar-15 1:25
Robowski16-Mar-15 1:25 
Questionmissing Code Pin
Ömer Demir14-Oct-13 8:16
Ömer Demir14-Oct-13 8:16 
GeneralMy vote of 3 Pin
Member 99934349-Jun-13 20:12
professionalMember 99934349-Jun-13 20:12 
Questionyes but Pin
zpaulo_carraca24-Apr-13 11:21
zpaulo_carraca24-Apr-13 11:21 
QuestionMissing code Pin
Andy Van Langendonck20-Feb-13 21:42
Andy Van Langendonck20-Feb-13 21:42 
AnswerRe: Missing code Pin
Harry Panesar21-Feb-13 0:23
Harry Panesar21-Feb-13 0:23 
GeneralRe: Missing code Pin
Andy Van Langendonck10-Mar-13 9:28
Andy Van Langendonck10-Mar-13 9:28 
GeneralRe: Missing code Pin
Harry Panesar12-Mar-13 6:47
Harry Panesar12-Mar-13 6:47 

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

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