我想扩展DataGridView以添加第二个ContextMenu,用于选择gird中可见的列。右键单击列的标题将显示新的ContextMenu。
我很难获得正确的水平位置来显示上下文菜单。我怎么能纠正这个?
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));
}
}
}
答案 0 :(得分:76)
这是一种非常简单的方法,可以在右键单击上方显示上下文菜单。
处理事件 ColumnHeaderMouseClick
private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
if (e.Button == System.Windows.Forms.MouseButtons.Right) {
contextMenuHeader.Show(Cursor.Position);
}
}
contextMenuHeader
是ContextMenuStrip
,可以在Designer视图中或在运行时定义。
答案 1 :(得分:15)
要获取鼠标光标的坐标,您可以执行此操作。
ContextMenu.Show(this, myDataGridView.PointToClient(Cursor.Position));
答案 2 :(得分:8)
您是否尝试过使用接受控件和位置的Show重载?
例如:
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);
}
}
}
}
答案 3 :(得分:4)
e.Location
不会在正确的坐标处显示弹出菜单,而只是使用MousePosition
属性,如下所示:
ContextMenuStrip.Show(MousePosition)
或者,明确地
ContextMenuStrip.Show(Control.MousePosition)
答案 4 :(得分:3)
返回的位置是相对于单元格的。所以我们必须添加那个偏移量。
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);
}
}
答案 5 :(得分: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));
}
}
}
}
答案 6 :(得分:1)
两次调用Show
将为您提供光标的确切位置。此答案适用于无法通过上述所有答案获得结果的人。
private void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(dataGrid, e.Location));
contextMenuStrip.Show(Cursor.Position);
}
}
答案 7 :(得分:1)
最后这对我有用。
ContextMenu.Show(myDataGridView, myDataGridView.PointToClient(Cursor.Position));
答案 8 :(得分:0)
你几乎是对的。您只需将PointToScreen
方法应用于调用控件:
private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(((DataGridView)sender).PointToScreen(e.Location));
}
}
我认为这是最优雅的解决方案,因为它只使用ColumnHeaderMouseClick
个参数,而不是Cursor.Position
。