2011-11-20 18 views
28

Tôi muốn mở rộng DataGridView để thêm một ContextMenu thứ hai để chọn những cột nào có thể nhìn thấy trong gird. ContextMenu mới sẽ được hiển thị trên kích chuột phải vào tiêu đề của cột.Làm cách nào để tôi định vị chính xác Trình đơn ngữ cảnh khi tôi nhấp chuột phải vào tiêu đề cột của DataGridView?

Tôi gặp khó khăn khi có được vị trí ngang chính xác để hiển thị menu ngữ cảnh. Làm thế nào tôi có thể sửa lỗi này?

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)); 
     } 
    } 
} 

Trả lời

1

Nơi tôi đã đi sai là DataGridViewCellMouseEventArgs trả về địa điểm/x, y của nơi chuột nhấp trong cột tiêu đề. Thay vào đó, tôi cần phải sử dụng HitTest trong sự kiện MouseDown của lưới điện cho một lần truy cập vào các tiêu đề cột và sau đó chuyển đổi vị trí của lần truy cập từ các tọa độ thứ thành tọa độ màn hình.

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

Bạn đã thử sử dụng Hiển thị quá tải chấp nhận điều khiển và vị trí chưa?

Ví dụ:

contextMenuStrip.Show(dataGrid, e.Location); 

Edit: Full dụ

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

Trình đơn nội dung xuất hiện ở góc trên cùng bên trái của màn hình vì vị trí e.location là vị trí chuột trong tiêu đề cột. Tôi đã giải quyết vấn đề ngay bây giờ nhưng cảm ơn vì đã giúp đỡ. –

+0

Theo câu trả lời của bạn cho câu hỏi của bạn e.location là trong datagrid, không columnheader, do đó authority_tech là chính xác. –

+0

Có vẻ như tôi đã kiểm tra câu trả lời của authority_tech kém và anh ấy thực sự đúng nếu được sử dụng trong sự kiện MouseDown. –

65

Đây là cách rất đơn giản để làm cho menu ngữ cảnh xuất hiện khi bạn nhấp chuột phải vào menu ngữ cảnh.

Xử lý sự kiện ColumnHeaderMouseClick

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

contextMenuHeader là một ContextMenuStrip có thể được định nghĩa trong giao diện thiết kế hoặc khi chạy.

+3

Đây phải là câu trả lời được chấp nhận. – Askolein

+3

+1: Phần liên quan của tôi là Cursor.Position (bây giờ tôi cảm thấy ngớ ngẩn) – NobodysNightmare

+0

Đơn giản nhưng mạnh mẽ –

13

Để có được tọa độ của con trỏ chuột, bạn có thể thực hiện việc này.

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

Điều này là chính xác. Câu trả lời được chấp nhận không biên dịch. – icanbenchurcat

3

e.Location không hiển thị các menu popup ở các tọa độ chính xác, thay vì chỉ cần sử dụng MousePosition tài sản như sau:

ContextMenuStrip.Show(MousePosition) 

hay, explicitely

ContextMenuStrip.Show(Control.MousePosition) 
0

Bạn là gần đúng. Bạn chỉ cần vào áp dụng phương pháp PointToScreen để kiểm soát cách gọi:

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

Tôi nghĩ rằng đây là giải pháp thanh lịch nhất, bởi vì nó chỉ ColumnHeaderMouseClick đối số và không Cursor.Position sử dụng.

2

Vị trí được trả về tương đối so với ô. Vì vậy, chúng tôi phải thêm bù đắp đó.

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); 
     } 
    } 
Các vấn đề liên quan