Click here to Skip to main content
11,491,742 members (69,989 online)
Click here to Skip to main content

Universal menu command handle pattern

, 8 Oct 2006 24.4K 23
Rate this:
Please Sign up or sign in to vote.
Universal menu command handle pattern

Introduction

(This article is translate version , original version written in chinese , you can see it at http://www.cnblogs.com/xdesigner/archive/2006/10/07/522927.html )
  Some WinForm application has a lot of menuitem , standard menum item in .NET framework is not perfect , so result in a lots of MenuItem_Click function , it is not easy to maintains those code , this article discuss a pattern which handle menu command universal .

  I think some people complain that a part of the standard WinForm library in .NET Framework 1.1 is poor , some body fleer that Microsoft employ hight middle school students to write System.Windows.Forms , of cause , this viewpoint is inflation . but in the author's experience , I find that a part of the standard WinForm library is really poor .
  Microsoft has thousands of good software engineer , according to it's power , it can provide a powerful , perfect standard WinForm library . Here , I guess microsoft publish a library with some disadvantage wilful . this is nothing but a business policy . Microsoft drop a blank and fetch the third party to exert . This  can maintenance the microsoft's empire. I think it is a good idea .
  Now talk about the content . In Winform application , you use a lot of menu , int VS.NET IDE , it provide a menu designer to design applicatin's menu structure , when you put a MainMenu or ContextMenu into a form , you can use menu designer to build menu item(type is System.Windows.Forms.MenuItem ) in a tree structure . and aim at every menuItem , you can write  code to handle it's Click event .
   This is fit to a small application , but not fit a big , complicated application with a lot of MenuItem , in a big applicatin , there are a lot of MenuItem_Click function , a WinForm application in a good design , it's logic collect together and call then use a single interface instead of distributed in lot's of MenuItem_Click or Button_Click functions . In this way , the MenuItem_Click function only call a single interface .
   For example , a from define a golbal logic function interface , define as "void HandleCommand( string Command )" , in this function there are a big switch structure , this function execute logic action bases parameter "Command" . Then in this form , there are some code like following

void MenuItem_Open_Click( object Sender , System.EventArgs e  )
{
    HandleCommand( "Open" );
}
void MenuItem_Save_Click( object Sender , System.EventArgs e  )
{
    HandleCommand( "Save" );
}

  There are a lot's of this kind of code is not a good smell , itt can be reform ,  you can let all MenuItem ' s Click event handler point to a same function , this function can write in

void MenuItem_Click( object Sender , System.EventArgs e )
{
    if( Sender == MenuItem_Open )
        HandleCommand( "Open" );
    else if( Sender == MenuItem_Save ) 
        HandleCommand( "Save" );
    else if ..........
}

  But this structure is not perfection , because people who write or maintain this  function must know every MenuItem's name , this is do harm to maintain code , If a MenuItem's function changed , you must change this MenuItem's name and modify MenuItem_Click's code .
  At there , How we hope than MenuItem type has Command property , if MenuItem has  property Command , then the universal menum click handler can write like

void MenuItem_Click( object Sender , System.EventArgs e )
{
    HandleCommand( ( ( MenuItem ) Sender ).Command );
}

  Very simple , easy to maintains , all you do is manage every MenuItem's Command property .
  But MenuItem has not Command property , so some people expend MenuItem type , build his owner MenuItem type , append Command property , then can use the universal MenuItem_Click function .
  At there , I did not create my owner MenuItem type , stand two point , first , IDE's MenuItem designer does not support Custom MenuItem type . Secend , there are  a lot of old application already use standard MenuItem type , Convert then to use Custom MenuItem type , it is a gread work.

   So I bring out a universal MenuItem command handler model , the primary code no more than 100 , it can support single handle menu command event without custom MenuItem type , this code is following


 

    public delegate void MenuCommandHandler( System.Windows.Forms.MenuItem MenuItem , string Command ); 
    public class MenuCommandSender
    {
        public MenuCommandSender()
        {
            myHandler = new EventHandler( this.MenuClick );
        }
        public event MenuCommandHandler MenuCommand = null;
        public void Clear()
        {
            foreach( BindItem item in myItems )
            {
                if( item.MenuItem != null )
                {
                    item.MenuItem.Click -= myHandler ;
                }
            }
            myItems.Clear();
        }
        public int Count
        {
            get{ return myItems.Count ;}
        }
        public void Registe( string strCommand , System.Windows.Forms.MenuItem MenuItem )
        {
            BindItem item = new BindItem();
            item.Command = strCommand ;
            item.MenuItem = MenuItem ;
            MenuItem.Click += myHandler ; 
            myItems.Add( item );
        }
        public string GetCommand( System.Windows.Forms.MenuItem MenuItem )
        {
            foreach( BindItem item in myItems )
            {
                if( item.MenuItem == MenuItem )
                    return item.Command ;
            }
            return null;
        }
        public System.Windows.Forms.MenuItem GetMenuItem( string strCommand )
        {
            foreach( BindItem item in myItems )
            {
                if( item.Command == strCommand )
                    return item.MenuItem ;
            }
            return null;
        } 
        private System.Collections.ArrayList myItems = new System.Collections.ArrayList();
        private class BindItem
        {
            public System.Windows.Forms.MenuItem MenuItem = null;
            public string Command = null;
        }
        private System.EventHandler myHandler = null;
        private void MenuClick( object sender , System.EventArgs e )
        {
            if( MenuCommand != null )
            {
                foreach( BindItem item in myItems )
                {
                    if( item.MenuItem == sender )
                    {
                        MenuCommand( item.MenuItem , item.Command );
                        break;
                    }
                }
            }
        }
    }//public class MenuCommandSender

   In your application , you create a MenuCommandSender instance , define a function as following and bind it to MenuCommandSender's MenuCommand event .

void HandleMenuCommand( MenuItem item , string Command )
{
    HandleCommand( Command );
}

  then use MenuCommandSender's Registe member function to registe menu command , for example

MenuCommandSender  cmd = new MenuCommandSender();
cmd.MenuCommand += new MenuCommandHandler( HandleMenuCommand );
cmd.Registe( "Open" , MenuItem_Open );
cmd.Registe( "Save" , MenuItem_Save );

  then , this pattern start . The work for convert old application use this model is  acceptable .
  In fact , this pattern can expend to handle System.Windows.Forms.Button or other WinForm control , not only System.Windows.Forms.MenuItem .
  This pattern is very simple and useful , I hope it is benefic to some developer who handle a lot of MenuItems .

XDesigner Studio ( http://www.xdesigner.cn/default-eng.htm ) 2006-10-9

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

yuan yong fu
Web Developer duchang soft
China China
yuan yong fu of duchang soft , come from CHINA , 2008 Microsoft MVP,Use GDI+,XML/XSLT, site:http://www.cnblogs.com/xdesigner/

Comments and Discussions

 
GeneralNice Pin
Simida19849-Oct-06 1:31
memberSimida19849-Oct-06 1:31 

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 | Terms of Use | Mobile
Web02 | 2.8.150520.1 | Last Updated 9 Oct 2006
Article Copyright 2006 by yuan yong fu
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid