2011-02-23 39 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); 
} 
相關問題