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

Where to define the menu items event handler

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

  1. 在定义为只读的行上
  2. 在可以编辑的行上
  3. 在网格中的任何其他位置(行索引为 -1)

我创建了一个新的 类 来管理弹出菜单的生成。

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 本身上完成。 例如,单击添加,将打开一个包含所有必填字段的临时表单,然后此信息将作为新行添加到 DataGridView 中。

在各自类.

的构造函数中

我认为它应该是这样的:

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;
    }
}