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

时间:2017-06-16 14:45:23

标签: c# winforms inheritance datagridview contextmenu

我有一个包含多个表单的项目。其中许多表单都有DataGridView和DataBound项,它们绑定到类Ticket的实例。我想给所有这些DataGridViews相同的ContextMenu。当用户右键单击DataGridView中的某一行,然后单击上下文菜单中的某个项目时,必须使用数据绑定Ticket完成某些操作。

为实现这一目标,我创建了一个基本表单,其他表单继承自。在这个基本形式中,我定义了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有一个子菜单,它由users实例中存储的Selection动态填充。这些菜单和子菜单都以从基本形式继承的形式完美地创建。

" 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)?

1 个答案:

答案 0 :(得分:1)

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

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

希望这有帮助!