【问题标题】:when click away still triggers Context Menu当点击离开时仍然触发上下文菜单
【发布时间】:2012-07-26 20:57:51
【问题描述】:

C# Winform 项目

我有一个带有 contextMenu 的 dataGridView。简单地说,一切都按我的意愿工作,除了上下文菜单选择触发,即使我不想要它(当我点击离开时)。 例如,我右键单击我的 dataGridView 我看到了我的选择。如果我选择它,它会触发 MouseClick 事件并执行我想要的操作。但是如果我点击它,它仍然会触发 MouseClick 事件。

我在 OnMouseUp 事件中以几种不同的方式进行了尝试,但同样的情况正在发生。您会在下面的代码中注意到一些额外的“如果”,这基本上是我尝试了一些事情来让 MouseClick 避免不必要地触发(尽管最后我相信它只是在做多余的工作)。

在下面的代码中,请注意以下内容:MessageBox.Show("something go wrong here!");

代码:

private void dgvMyDataGridView_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        currentMouseOverCol = dgvMyDataGridView.HitTest(e.X, e.Y).ColumnIndex;
        currentMouseOverRow = dgvMyDataGridView.HitTest(e.X, e.Y).RowIndex;

        ContextMenu m = new ContextMenu();
        if (currentMouseOverRow >= 0 && currentMouseOverCol == 1)
        {
            dgvMyDataGridView.CurrentRow.Cells[0].Value.ToString())));
            m.MenuItems.Add(new MenuItem(string.Format("Do something with this row")));
        }

        m.Show(dgvMyDataGridView, new Point(e.X, e.Y));
    }

    DataGridView.HitTestInfo hitTestInfo;
    hitTestInfo = dgvMyDataGridView.HitTest(e.X, e.Y);

    if (hitTestInfo.Type == DataGridViewHitTestType.Cell && hitTestInfo.ColumnIndex == 1 && currentMouseOverRow >= 0 && currentMouseOverCol == 1)
    {
        MessageBox.Show("something goes wrong here!");
        // Code to open a new form page - this all works.
    }
}

我缺少什么来告诉我的应用程序在我点击离开时不触发?

谢谢,

~克里斯

【问题讨论】:

  • 不要这样创建上下文菜单,创建一个静态上下文菜单然后设置dgvMyDataGridView.ContextMenu = m;
  • @HansZ 他希望它是静态的吗?有可能(可能不是他的情况)表单可以被多次实例化,然后单击任何表单上的菜单会触发所有附加的处理程序,对吗?不只是表单的常规成员变量是要走的路吗?或者甚至为 DataGridView 设置 ContextMenu 属性,然后重新使用它?
  • 老实说,我不记得我为什么要动态创建它。我相信这与我必须创建一个动态构建的 ContextMenu 的认识有关(我有一个程序员的想法,但很抱歉我没有你们那么有经验)。无论如何,我是如此接近,我不想重做所有事情,所以我坚持下去,并相信我解决了我的问题。我需要做的是通过 contextMenu 创建一个事件处理程序,而不是使用 dgvMyDataGridView_MouseClick 事件。谢谢大家的意见。

标签: c# winforms datagridview contextmenu


【解决方案1】:

发生的情况是,一旦 ContextMenu 关闭,您的方法将继续处理。要修复您的解决方案,您只需在为您的 ContextMenu 调用 Showreturn

简单修复:

m.Show(dgvMyDataGridView, new Point(e.X, e.Y));
return;

问题在于事件处理程序的执行仍在继续,只是在上下文菜单关闭时等待m.Show“结束”,类似于Form.ShowDialogMessageBox.Show 的行为方式。

更新:从评论看来,DataGridView.MouseClick 试图处理用户点击 ContextMenu 的项目。在这种情况下,您需要对代码进行较大的更改,如下所示:

private void dgvMyDataGridView_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        var hitTestInfo = dgvMyDataGridView.HitTest(e.X, e.Y);

        if ((hitTestInfo.Type == DataGridViewHitTestType.Cell) &&
            (hitTestInfo.ColumnIndex == 1) &&
            (hitTestInfo.RowIndex >= 0))
        {
            string currentCell = dgvMyDataGridView.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex].Value.ToString();
            ContextMenu m = new ContextMenu();
            dgvMyDataGridView.CurrentRow.Cells[0].Value.ToString();
            m.MenuItems.Add(new MenuItem("Click Me!", new EventHandler((itemSender, itemEvent) =>
            {
                var result = MessageBox.Show("You've clicked " + currentCell + ". Open next form?", "Continue?", MessageBoxButtons.YesNo);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    // Code to open a new form page.
                }
            })));
            m.Show(dgvMyDataGridView, new Point(e.X, e.Y));
        }
    }
}

关键是将 EventHandler 添加到 ContextMenu 的 MenuItem 中。希望对您有所帮助!

【讨论】:

  • 我相信你在做某事。奇怪的是,它曾经工作过一次,但出于某种原因,在那之后就没有了。我整天都在搞乱我的代码,我可能在某个时候破坏了一些东西。我离得太近了,我不想重做所有事情,所以我坚持下去,相信我解决了我的问题。我需要做的是通过 contextMenu 创建一个事件处理程序,而不是使用 dgvMyDataGridView_MouseClick 事件。记录如下:m.MenuItems.Add("&Do Something ", new EventHandler(EventToCallHere));然后我设置一个事件来做我想做的事。非常感谢您的帮助。
  • @Chris Ah,所以您是说 MouseClick 处理程序的第二部分是 ContextMenu 的预期结果?这是一个关键点,我将更新我的答案以包含该修复,以便稍后搜索类似问题的任何人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 2019-10-14
  • 1970-01-01
相关资源
最近更新 更多