• Universal menu command handle pattern


    Universal menu command handle pattern
    summary
    (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

  • 相关阅读:
    201805140815_《缓存操作函数封装》
    201802071223_《更换两个二进制》
    201801301359——《注意Javascript这种形式》
    201708310807_《算法-Javascript实现最大公约数》
    重拾java openjdk1.8 语法小试
    代码轮子之很简单但是挺管用的基于C# Task的模拟并发的代码
    docker1.12 安装pxc(Percona XtraDB Cluster )测试
    .net orm比较之dapper和Entity Framework6的简单测试比较
    StackExchange.Redis使用和封装小试
    docker1.12 安装redis3官方集群 攻略
  • 原文地址:https://www.cnblogs.com/xdesigner/p/524865.html
Copyright © 2020-2023  润新知