2011-11-20 7 views
28

DataGridViewを拡張して、2番目のContextMenuを追加して、どの列をgirdで表示するかを選択したいと考えています。新しいContextMenuは、列のヘッダーを右クリックして表示されます。DataGridViewの列ヘッダーを右クリックすると、コンテキストメニューの位置を正しく設定できますか?

コンテキストメニューを表示するのに正しい水平位置が得られません。どうすれば修正できますか?

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     dataGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(ColumnHeaderMouseClick); 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      contextMenuStrip.Show(PointToScreen(e.Location)); 
     } 
    } 
} 

答えて

1

はどこで間違ってDataGridViewCellMouseEventArgsは、マウスが列内をクリックした場所の位置/ X、Yを返すことにありましたヘッダ。代わりに、グリッドのMouseDownイベントでHitTestを使用して列見出しをヒットし、ヒットの位置をガード座標からスクリーン座標に変換する必要があります。

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     //dataGrid.ColumnHeaderMouseClick += ColumnHeaderMouseClick; 
     dataGrid.MouseDown += MouseDown; 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      contextMenuStrip.Show(PointToScreen(e.Location)); 
     } 
    } 

    private void MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader) 
      { 
       contextMenuStrip.Show(dataGrid.PointToScreen(e.Location)); 
      } 
     } 
    } 
} 
8

コントロールと位置を受け入れるオーバーロードを表示しようとしましたか?

contextMenuStrip.Show(dataGrid, e.Location); 

編集:例えば

全例

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     dataGrid.MouseDown += MouseDown; 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader) 
      { 
       contextMenuStrip.Show(dataGrid, e.Location); 
      } 
     } 
    } 
} 
+0

コンテンツメニューは、画面の左上隅に表示されます.e.locationは列見出し内のマウスの位置です。私は今問題を解決しましたが、助けてくれてありがとう。 –

+0

あなたの質問に答えたところ、e.locationはcolumnheaderではなくdatagrid内にあるため、competent_techは正しいです。 –

+0

competent_techの回答がうまくいかなかったようですが、MouseDownイベントで使用された場合、彼は確かに正しいです。 –

65

ここでは、コンテキストメニューを右クリックすると表示される非常に簡単な方法です。

ColumnHeaderMouseClick

private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) { 
    contextMenuHeader.Show(Cursor.Position); 
    } 
} 

contextMenuHeaderがデザイナービューまたは実行時に定義することができますContextMenuStripでイベントを処理します。

+3

これは受け入れられる回答である必要があります。 – Askolein

+3

+1:私のための関連する部分はCursor.Position(今私は愚かな感じです) – NobodysNightmare

+0

シンプルだがパワフル –

13

マウスカーソルの座標を取得するには、これを行うことができます。

ContextMenuStrip.Show(MousePosition) 

または、明示的に

ContextMenuStrip.Show(Control.MousePosition) 
+1

これは正しいです。受け入れられた答えはコンパイルされません。 – icanbenchurcat

3

e.Locationは、次のようにだけでなくMousePositionプロパティを使用し、正しい座標にポップアップメニューが表示されません。私はそれだけでColumnHeaderMouseClick引数としませCursor.Positionを使用しているため、これは、最もエレガントな解決策だと思う

private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
{ 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) 
    { 
     contextMenuStrip.Show(((DataGridView)sender).PointToScreen(e.Location)); 
    } 
} 

:あなただけの呼び出し制御にPointToScreen方法を適用する必要があります。

0

あなたはほぼ正しかったの:

ContextMenu.Show(this, myDataGridView.PointToClient(Cursor.Position)); 
2

返される位置はセルを基準にしています。そのオフセットを追加する必要があります。

private void grdView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Right) 
     { 
      var pos = ((DataGridView)sender).GetCellDisplayRectangle(e.ColumnIndex, 
      e.RowIndex, false).Location; 
      pos.X += e.X; 
      pos.Y += e.Y; 
      contextMenuStrip.Show((DataGridView)sender,pos); 
     } 
    } 
関連する問題