Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Bridge the Gap between Menu Controls and Command Pattern

4.50/5 (3 votes)
28 Jun 2008CPOL3 min read 1   227  
This article illustrates a case where I apply Command Pattern to ASP.NET Menu controls
CommandMenuDemo

Introduction

Applying design patterns to practical software development is pretty interesting, and only when you attempt to apply can you grasp the merits described in textbooks. This article illustrates a case where I apply the Command Pattern to ASP.NET Menu controls. I also demonstrate the implementation of a generic command with Delegate whereby developers can “reuse” to achieve their implementation without creating new command classes.

Problem Description

All ASP.NET Menu controls are most commonly applied to display the hyperlink structures (i.e. Site Map) of a Web site. However, you may want to use it to implement a scenario that after users click one of the menu items on the client-side, your program will react on the server-side according to the menu item clicked (e.g. MenuItem.Text). Let’s take RadMenu (within Telerik’s RadControls) as an example; you do not need to know the nuts and bolts of RadMenu to continue (and the thought discussed below can be applied to various Menu controls). The most intuitive solution often results in the implementation of an “if---else” construct as follows:

C#
protected void DefaultRadMenu_ItemClick(object sender, Telerik.Web.UI.RadMenuEventArgs e)
{
             RadMenuItem selItem = e.Item;

             if(selItem.Text == "Apple")
             {
                 doApple();
             }
             else if(selItem.Text == "Orange")
             {
                 doOrange();
             }
             else
             {
                 // do something
             }
}

DefaultRadMenu_ItemClick is a handler for any menu item clicked (postback=true). If you have taken a look at articles talking about design pattern or code maintainability, you should have smelt what the problem is: once a new item called lemon comes out, not only do you need to implement doLemon(), but you must also modify the “ifelse” construct. Furthermore, if your application contains many pages which individually use RadMenu to do different things, you have to tediously repeat this kind of code pattern throughout your application. Here Command pattern comes to the rescue.

Apply Command Pattern with Menu Controls

Command pattern is a highly prevailing design pattern in OOP. If you are not familiar with it, please Google by yourself! In this article, Command pattern is designed with an interface IMenuItemCommand (shown below) and we provide a default generic command: the BaseMenuItemCommand class described shortly; of course, you can implement your IMenuItemCommand concrete class for rescue through the application. IMenuItemCommand simply defines the behavior of a command shown as follows:

C#
public interface IMenuItemCommand
{
   // Execute Command
   void Execute();

   // Describe the command
   string Text { get; set;}
}

The Execute() is where the server-side reaction is customized by you. With the command pattern, we can implement a generic ItemClicked handler, which can be reused everywhere:

C#
protected void DefaultRadMenu_ItemClicked
    (object sender, Telerik.Web.UI.RadMenuEventArgs e)
{
             RadMenuItem selItem = e.Item;
             IMenuItemCommand itemCmd = selItem.DataItem as IMenuItemCommand;

             if (itemCmd != null)
             {
                 itemCmd.Execute();
             }
}

Notice that in order to let the preceding DefaultRadMenu_ItemClicked work, we must assign a concrete IMenuItemCommand object (i.e. BaseMenuItemCommand) into RadMenuItem.DataItem when building the RadMenu:

C#
RadMenuItem item1 = new RadMenuItem("Hello");

item1.DataItem = new BaseMenuItemCommand (
delegate {
//do something on server-side;
});

RadMenu1.Items.Add(item1);

The above code snippet also demonstrates the use of the generic command, BaseMenuItemCommand. The parameter in the constructor is a delegate (i.e. ToDoDelegate in the following code) that is executed within BaseMenuItemCommand.Execute() shown below:

C#
public void Execute()
{
    if(ToDo != null)
    {
        ToDo();
    }
}

…

private ToDoDelegate _toDo;

public ToDoDelegate ToDo
{
    get { return _toDo; }
    set { _toDo = value; }
}

public delegate void ToDoDelegate();

The purpose of BaseMenuItemCommand is to let you reuse this class to implement a variety of commands. Imagine if you get 10 menu items whose commands cannot be reused elsewhere. Would you like to implement 10 separate IMenuItemCommand classes to complicate your system?

In sum, applying the Command Pattern to Menu controls eliminates the “if-else” construct among pages using Menu. Also, commands can possibly be reused via other Menu controls. More importantly, your codes with Command Pattern become more consistent than without it, resulting in more maintainable code.

Conclusion

I hope this code sample could help you diminish the repetitive codes when you decide to employ Menu controls to implement the scenario described in this article. Although we specifically use RadMenu to demonstrate the application of the Command Pattern, the concept can definitely be applied to other Menu controls.

History

  • 24th June, 2008: Initial article submitted

License

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