在哪里定义菜单项事件处理程序

时间:2016-01-27 10:05:40

标签: c# winforms design-patterns menu architecture

我在WinForm上有一个DataGridView。当用户右键单击网格时,我显示一个弹出菜单。根据右键单击的位置,有3种弹出菜单:

  1. 在一行定义为readonly
  2. 在可以编辑的行上
  3. 在网格中的任何其他位置(rowindex为-1)
  4. 我创建了一个新类来管理弹出菜单的生成。

    public class GridPopupMenuFactory
    {
        public ContextMenu GetMenu(int rowIndex, bool isReadOnlyRow)
        {
            BaseMenu _menu = null;
    
            switch (rowIndex)
            {
                case -1:
                    _menu = new GeneralMenu();
                    break;
                default:
                    if (isReadOnlyRow)
                    {
                        _menu = new ReadonlyRowMenu();
                    }
                    else
                    {
                        _menu = new EditableRowMenu();
                    }
                    break;
            }
    
            return _menu.Menu;
        }
    }
    
    public abstract class BaseMenu
    {
        protected ContextMenu _menu;
        public ContextMenu Menu
        {
            get
            {
                if (_menu.MenuItems.Count == 0)
                {
                    GenerateMenu();
                }
                return _menu;
            }
        }
    
        protected abstract void GenerateMenu();
    }
    
    public class GeneralMenu : BaseMenu
    {
        protected override void GenerateMenu()
        {
            var contextMenu = new ContextMenu();
    
            contextMenu.MenuItems.Add(new MenuItem("Sort"));
            contextMenu.MenuItems.Add(new MenuItem("Print"));            
    
            _menu = contextMenu;
        }
    }
    
    public class ReadonlyRowMenu : BaseMenu
    {
        protected override void GenerateMenu()
        {
            var contextMenu = new ContextMenu();
    
            contextMenu.MenuItems.Add(new MenuItem("View"));            
    
            _menu = contextMenu;
        }
    }
    
    public class EditableRowMenu : BaseMenu
    {
        protected override void GenerateMenu()
        {
            var contextMenu = new ContextMenu();
    
            contextMenu.MenuItems.Add(new MenuItem("Add"));
            contextMenu.MenuItems.Add(new MenuItem("Edit"));
            contextMenu.MenuItems.Add(new MenuItem("Delete"));
    
            _menu = contextMenu;
        }
    }
    
    // Winform
    private void shipmentDetailsDataGridView_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                var rowIndex = shipmentDetailsDataGridView.HitTest(e.X, e.Y).RowIndex;
                var popupMenu = GridPopupMenu.GetMenu(rowIndex, false);  // 2nd parameter can be true, TODO
    
                popupMenu.Show(shipmentDetailsDataGridView, new Point(e.X, e.Y));
            }
        }
    

    我的问题是为每个菜单项定义事件处理程序的正确位置在哪里?

    更新: 单击菜单项后,整个操作将在DataGridView上完成。 例如,单击add,将打开包含所有必填字段的临时表单,然后此信息将作为DataGridView中的新行添加。

2 个答案:

答案 0 :(得分:1)

在各个类的构造函数中。

答案 1 :(得分:1)

我相信它应该是这样的:

public class GeneralMenu : BaseMenu {
    protected override void GenerateMenu() {
        var contextMenu = new ContextMenu();
        contextMenu.MenuItems.Add(new MenuItem("Sort", OnSort));
        contextMenu.MenuItems.Add(new MenuItem("Print", OnPrint));
        _menu = contextMenu;
    }
    void OnSort(object sender, EventArgs e) {
        var gridView = GetSourceControl<DataGridView>(sender);
        if(gridView != null) {
            // do sort
        }
    }
    void OnPrint(object sender, EventArgs e) {
        var gridView = GetSourceControl<DataGridView>(sender);
        if(gridView != null) {
            // do print
        }
    }
    static TControl GetSourceControl<TControl>(object sender) where TControl : Control {
        var menu = ((MenuItem)sender).GetContextMenu();
        return (menu != null) ? menu.SourceControl as TControl : null;
    }
}
相关问题