通过从另一个窗体继承的ContextMenu子菜单检索DataGridView中的对象

Retrieve object in DataGridView through ContextMenu submenu inherited from another form

我有一个包含多个表单的项目。其中许多表单都有一个带有 DataBound 项的 DataGridView,它们绑定到 Class Ticket 的实例。我想为所有这些 DataGridView 提供相同的 ContextMenu。当用户右键单击 DataGridView 中的一行,然后单击上下文菜单中的项目时,必须对数据绑定 Ticket.

做一些事情

为此,我创建了一个其他表单继承的基本表单。在这个基本表单中,我定义了 ContextMenu(我以前没有使用过 contextmenu,所以这是反复试验,我不确定这是最好的方法。):

public ContextMenuStrip ContextTicket;

public frmBaseForm()
{
    InitializeComponent();
    ContextTicket = new ContextMenuStrip();

    var itemEdit = ContextTicket.Items.Add("Edit ");
    itemEdit.Click += itemEdit_Click;

    var itemAssign = ContextTicket.Items.Add("Assign to");

    foreach (var user in Selection.Users)
    {
        ToolStripItem item = (itemAssign as ToolStripMenuItem).DropDownItems.Add(user.Name);
        item.Click += itemAssign_Click;
    }

    var itemSetToFixed = ContextTicket.Items.Add("Set Fixed");
    itemSetToFixed.Click += itemSetToFixed_Click;
}

想法是:上下文菜单有 3 个菜单项;编辑、设置固定和分配。 Assign Item 有一个子菜单,它动态填充存储在 Selection 实例中的 users。这些菜单和子菜单都在从基本窗体继承的窗体中创建得非常好。

我开始工作的 "Set Fixed" 项目背后的功能,我像这样检索相关的 Ticket

public void itemSetToFixed_Click(object sender, EventArgs e)
{
    var ticket = getTicket(sender);

    /*
       Do something with Ticket
    */
}

private Ticket getTicket(object sender)
{
    try
    {
        ToolStripItem clickedItem = sender as ToolStripItem;

        ContextMenuStrip owner = clickedItem?.Owner as ContextMenuStrip;
        DataGridView control = owner?.SourceControl as DataGridView;            

        var obj = control?.SelectedRows[0].DataBoundItem; 

        if (obj is Ticket)
        {
            return (Ticket)obj;
        }
        else
        {
            return null;
        }

    }
    catch (Exception e)
    {
        MessageBox.Show("Error", "Unable to retrieve ticket information from selection.");
        return null;
    }    
}

不过,我无法从分配项目的子菜单中检索选定的 Ticket。当我来自子菜单时,clickedItem.OwnerToolStripDropDownMenu,我似乎无法再进入 DataGridView 级别。

如何从 ContextMenu 的子菜单转到 DataGridView 中的原始单击行(即 Ticket)?

在你的DataGridView鼠标点击事件监听方法上,把发送者当成一个DataGridView:

private void DataGridViewMouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        DataGridView dgv = sender as DataGridView;
        if (dgv != null)
        {
            // find the current index
            int currentIndex = dgv.CurrentRow.Index;
            // find the current Ticket
            Ticket currentTicket = dgv.CurrentRow.DataBoundItem as Ticket;

            ContextMenu menu = new ContextMenu();
            // set up the context menu here...
            menu.Show(dgv, new Point(e.X, e.Y));
        }
    }
}

如果您愿意,可以通过其他方式分配 dgv 和 currentTicket 对象:

DataGridView dgv = (DataGridView) sender;
Ticket currentTicket = (Ticket) dgv.CurrentRow.DataBoundItem;

就查找当前索引而言,用户必须在此方法正常工作之前已经单击了某些内容...因此明智的做法是在此处进行检查以确保已完成此操作。

希望这对您有所帮助!