我想在DataGridView的右键单击上放置一个上下文相关菜单。我希望有一个菜单项是从单击的单元格的内容派生而来的,而子菜单中有可变数量的项是从数据库中检索到的。

我通过在ContextMenuStrip Opening事件中构建ToolStripMenuItem来实现。而且有效-几乎...

如果我不显示子菜单,那么用户必须单击顶级菜单中的单个项目,一切都很好,但是如果我调用ShowDropDown方法以自动显示子菜单,则在单击项目时不会激活现有功能。

这是我可以产生的最简单的代码来重现该问题-我拔出了对DataGridView和数据库的所有引用,因此我的“动态”菜单绝对是静态的;-)

如果您输入的是表单定义,请在表单上的任意位置单击鼠标右键,然后会看到有效的行为,但不是您想要的行为-单击子菜单,然后弹出一个窗口。勾选复选框并再次右键单击,您将看到子菜单自动弹出-但是单击项目不会触发aliasClick处理程序。

有什么想法吗?在这个特定的应用程序中,我可以编写一个可以避免使用ShowDropDown的完全可行的解决方法-但是我想知道自己在做错什么,以防将来需要使用它。

public partial class Form1 : Form
{
    private ContextMenuStrip cms;
    private CheckBox chkAuto;

    public Form1()
    {
        InitializeComponent();

        chkAuto = new CheckBox();
        Controls.Add(chkAuto);

        cms = new ContextMenuStrip();
        cms.Opening += contextMenuStrip1_Opening;

        this.MouseClick += Form1_MouseClick;
    }

    private void Form1_MouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Right)
            cms.Show(Cursor.Position);
    }

    private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
    {
        cms.Items.Clear();
        ToolStripMenuItem tsmi = new ToolStripMenuItem("Title from datagridviewcell");
        tsmi.DropDownItems.Add(new ToolStripMenuItem("First item from database lookup", null, aliasClick));
        tsmi.DropDownItems.Add(new ToolStripMenuItem("Second item from database lookup", null, aliasClick));
        tsmi.DropDownItems.Add(new ToolStripMenuItem("Last item from database lookup", null, aliasClick));
        cms.Items.Add(tsmi);
        if (chkAuto.Checked)
            tsmi.ShowDropDown();
        e.Cancel = false;
    }
    private void aliasClick(object sender, EventArgs e)
    {
        ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
        MessageBox.Show(clickedItem.Text);
    }
}

最佳答案

我不确定如何证明这一点,但是我怀疑您对tsmi.ShowDropDown()的调用在某种程度上导致单击处理程序无法正确捕获坐标。将其替换为cms.Show(MousePosition)即可。

也许通过查看坐标可以收集到一些有用的信息...

var mi = new ToolStripMenuItem("First item from database lookup", null, aliasClick);
tsmi.DropDownItems.Add(mi);
var mi2 = new ToolStripMenuItem("Second item from database lookup", null, aliasClick);
tsmi.DropDownItems.Add(mi2);
var mi3 = new ToolStripMenuItem("Last item from database lookup", null, aliasClick);
tsmi.DropDownItems.Add(mi3);
cms.Items.Add(tsmi);
if (chkAuto.Checked)
    tsmi.ShowDropDown();
    //cms.Show(MousePosition);
Debug.WriteLine(mi.Bounds.ToString());

10-08 08:51