2011-02-23 36 views
6

在我的应用程序中,我有一个DataGridView,用于配置某些选项。这个想法是,你可以在第一列输入你想要的任何文本,但如果你右键点击它会给你显式支持的值。我需要这是一个文本框而不是下拉列表,因为我需要支持编辑无效(或旧)配置。为什么我的WinForms上下文菜单不出现在鼠标所在的位置?

我想要的是用户在字段名称列中右键单击并具有基于这是什么类型的配置有效的上下文菜单。因此,我编写了以下事件

private void grvFieldData_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     // If this is a right click on the Field name column, create a context menu 
     // with recognized options for that field 
     if (e.Button == MouseButtons.Right && grvFieldData.Columns[e.ColumnIndex].Name == "clmFieldName") 
     { 
      ContextMenu menu = new ContextMenu(); 

      if (_supportedDataGrids.ContainsKey((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)) 
      { 
       // Loop through all the fields and add them to the context menu 
       List<string> fields = _supportedDataGrids[((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)]; 
       fields.Sort(); 

       foreach (string field in fields) 
        menu.MenuItems.Add(new MenuItem(field)); 

       // Make sure there is at least one field before displaying the context menu 
       if (menu.MenuItems.Count > 0) 
        menu.Show(this, e.Location, LeftRightAlignment.Right); 
      } 
     } 
    } 

这工作“正常”,但上下文菜单出现在表单的顶部,而不是当鼠标指针。如果我将Show()调用更改为使用DataGridView而不是表单,我遇到了同样的问题,但它出现在网格的左上角,而不是鼠标所在的位置。奇怪的是,如果我将此事件更改为MouseClick事件(而不是CellMouseclick事件),则一切正常,上下文菜单正好出现在鼠标指针所在的位置。这个选项的问题在于用户可能不是右键单击当前选中的单元格,这意味着当他们点击菜单项时,所选单元格将被更改,而不是他们右键单击的单元格。

有没有人有任何暗示为什么用CellMouseClick创建的上下文菜单没有显示在正确的位置?

回答

17
menu.Show(this, e.Location, LeftRightAlignment.Right); 

的第二个参数是鼠标的位置,相对于细胞的左上角。按照编程设置,您可以从这个(该窗体将使菜单显示在窗体的左上角)中作出相对偏移。使用DGV作为第一个参数也不起作用,现在它位于网格的左上角。

一对夫妇的方式来解决这个问题,但是这是最简单的方法:

Point pos = this.PointToClient(Cursor.Position); 
menu.Show(this, pos, LeftRightAlignment.Right); 

您可以随意更换与grvFieldData。

+0

嘿,我的答案会稍微复杂一些X和Y坐标的添加。我希望我几周前知道Cursor.Position!为简单起见+1! – Yetti 2011-02-23 17:17:00

+0

真棒,那就像一个魅力! 'Cursor.Position'是我错过的! – KallDrexx 2011-02-23 17:20:29

1

尝试使用PointToClient得到适当的点

+0

都能跟得上。 'PointToClient(e.Location)'将上下文菜单放在屏幕的顶部,并且'PointToScreen(e.Location)'将上下文菜单放在表单中间,出于某种原因。 – KallDrexx 2011-02-23 16:51:18

+0

grvFieldData.PointToClient(e.Location) – Stecya 2011-02-23 16:52:28

+0

同样的问题,即使我将'this'调用更改为'grvFieldData': -/ – KallDrexx 2011-02-23 16:55:10

1

这不是在正确的位置上显示,因为e.Location是相对父对象的左上角,在这种情况下是细胞本身的位置。位置属性总是相对于它们的容器。

为了获得相对于形式本身的左上角的鼠标光标的位置,你可以使用

this.PointToClient(Cursor.Position); 
+0

如何获取单击单元格的位置(单元格不是如此控制的我不能将它传递到Show()')或鼠标的屏幕位置? – KallDrexx 2011-02-23 17:09:11

+0

看到我编辑的答案。 – MartW 2011-02-23 17:20:52

1

我已经解决了这个问题......人们可以发现这种方法很奇怪,但它工作正常!) 如果我们想看到一个上下文菜单,而在DataGridView单元格中按鼠标右键BTN,并在那里,而不是在屏幕或其他地方的中间,我们需要:

做出一些变量

int x=0; 
int y=0; 

做出 '的MouseMove' 事件datagridview1艾克说:

private void dataGridView1_MouseMove(object sender, MouseEventArgs e) 
{ 
    x = e.X; 
    y = e.Y; 
} 

private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
{ 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) 
    { 
     contextMenuStrip1.Show(dataGridView1, x,y); 
    } 
} 

的欢迎

+0

该解决方案具有不必要的开销,因为用户将鼠标移动到网格上(我认为这经常会发生),它会不断写入内存。该事件已包含该位置。 – 2012-11-02 17:22:27

3

在DataGridView鼠标点击事件:

if e.button= mousebutton.right 
{ 
    contextmenu1.Show(MousePosition); 
} 
相关问题