DataGridView列右击菜单事件
DGV上的鼠标事件,MouseDown 、MouseUp、CellMouseClick等事件可参考。
if (MouseButtons == MouseButtons.Right)
MessageBox.Show("OK");
// DataGridView 的 ContextMenuStrip 设定
DataGridView1.ContextMenuStrip = this.ContextMenuStrip1;
// 列的 ContextMenuStrip 设定
DataGridView1.Columns[0].ContextMenuStrip = this.ContextMenuStrip2;
// 列头的 ContextMenuStrip 设定
DataGridView1.Columns[0].HeaderCell.ContextMenuStrip = this.ContextMenuStrip2;
// 行的 ContextMenuStrip 设定
DataGridView1.Rows[0].ContextMenuStrip = this.ContextMenuStrip3;
// 单元格的 ContextMenuStrip 设定
DataGridView1[0, 0].ContextMenuStrip = this.ContextMenuStrip4;
对于单元格上的右键菜单的设定,优先顺序是: Cell > Row > Column > DataGridView
? CellContextMenuStripNeeded、RowContextMenuStripNeeded 事件
利用 CellContextMenuStripNeeded 事件可以设定单元格的右键菜单,尤其但需要右键菜单根据单元格值的变化而变化的时候。比起使用循环遍历,使用该事件来设定右键菜单的效率更高。但是,在DataGridView使用了DataSource绑定而且是VirtualMode的时候,该事件将不被引发。
// CellContextMenuStripNeeded事件处理方法
private void DataGridView1_CellContextMenuStripNeeded(object sender,
DataGridViewCellContextMenuStripNeededEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
if (e.RowIndex < 0)
{
// 列头的ContextMenuStrip设定
e.ContextMenuStrip = this.ContextMenuStrip1;
}
else if (e.ColumnIndex < 0)
{
// 行头的ContextMenuStrip设定
e.ContextMenuStrip = this.ContextMenuStrip2;
}
else if (dgv[e.ColumnIndex, e.RowIndex].Value is int)
{
// 如果单元格值是整数时
e.ContextMenuStrip = this.ContextMenuStrip3;
}
}
//同样,可以通过 RowContextMenuStripNeeded 事件来设定行的右键菜单。
// RowContextMenuStripNeeded事件处理方法
private void DataGridView1_RowContextMenuStripNeeded(object sender,
DataGridViewRowContextMenuStripNeededEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
// 当"Column1"列是Bool型且为True时、设定其的ContextMenuStrip
object boolVal = dgv["Column1", e.RowIndex].Value;
Console.WriteLine(boolVal);
if (boolVal is bool && (bool)boolVal)
{
e.ContextMenuStrip = this.ContextMenuStrip1;
}
}
//CellContextMenuStripNeeded 事件处理方法的参数中、「e.ColumnIndex=-1」表示行头、「e.RowIndex=-1」表示列头。RowContextMenuStripNeeded则不存在「e.RowIndex=-1」的情况。
//引用地址 http://qianshao.blog.51cto.com/935360/201791
//How do you select a datagridview row on a right-click?
// Clear all the previously selected rows
foreach (DataGridViewRow row in yourDataGridView.Rows)
{
row.Selected = false;
}
// Get the selected Row
DataGridView.HitTestInfo info = yourDataGridView.HitTest( e.X, e.Y );
// Set as selected
yourDataGridView.Rows[info.RowIndex].Selected = true;
//You can use JvR's code in the MouseDown event of your DataGridView.
private void SubClassedGridView_MouseDown(object sender, MouseEventArgs e)
{
// Sets is so the right-mousedown will select a cell
DataGridView.HitTestInfo hti = this.HitTest(e.X, e.Y);
// Clear all the previously selected rows
this.ClearSelection();
// Set as selected
this.Rows[hti.RowIndex].Selected = true;
}
private void dataGridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
dataGridView.CurrentCell = dataGridView[e.ColumnIndex, e.RowIndex];
}
}
控制右键菜单出现的位置为鼠标点击的地方呢?
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
int r = this.dataGridView1.HitTest(e.X, e.Y).RowIndex;
int c = this.dataGridView1.HitTest(e.X, e.Y).ColumnIndex;
if (r >= 0 && c >= 0) //点中Cell
{
DataGridViewCell hitcell = this.dataGridView1.Rows[r].Cells[c];
Point pscreen = this.dataGridView1.PointToScreen(e.Location);
Point pForm = this.PointToClient(pscreen);
this.textBox1.Text = pscreen.ToString(); //相对屏幕的坐标
this.textBox2.Text = pForm.ToString(); //相对当前Form的坐标
}
else //没点中Cell
{
}
}
CellContextMenuStripNeeded 事件仅在设置了 DataGridView 控件的 DataSource 属性或者该控件的 VirtualMode 属性为 true 时发生。
处理 CellContextMenuStripNeeded 事件时,每当用户右击单元格时,就会显示您在处理程序中指定的快捷菜单。当需要显示由某个单元格的当前状态或当前值决定的快捷菜单时,此事件就很有用。
只要检索 DataGridViewCell.ContextMenuStrip 属性的值,无论是通过编程方式还是用户右击某个单元格,CellContextMenuStripNeeded 事件都会发生。
可以使用 ColumnIndex 和 RowIndex 属性来确定单元格的状态或值,并使用这些信息来设置 ContextMenuStrip 属性。此属性是使用单元格的 ContextMenuStrip 属性值初始化的,该值会被事件值重写。
在处理大量数据时应处理 CellContextMenuStripNeeded 事件,这样,在为多个单元格设置单元格 ContextMenuStrip 值时,可以避免性能受到影响。有关更多信息,请参见 缩放 Windows 窗体 DataGridView 控件的最佳做法。
还可以通过设置行的 ContextMenuStrip 属性或处理 DataGridView 控件的 RowContextMenuStripNeeded 事件来为各个行(而非各个单元格)指定快捷菜单。单元格的 ContextMenuStrip 属性设置重写行的 ContextMenuStrip 属性设置,CellContextMenuStripNeeded 事件既重写 RowContextMenuStripNeeded 事件,又重写行的 ContextMenuStrip 属性设置。不过,您可以为单元格快捷菜单指定 空引用(在 Visual Basic 中为 Nothing) 来阻止重写行快捷菜单。
有关处理事件的更多信息,请参见 使用事件。
当创建 DataGridViewCellContextMenuStripNeededEventHandler 委托时,将标识处理事件的方法。若要使该事件与事件处理程序相关联,请将该委托的一个实例添加到事件中。除非移除了该委托,否则每当发生该事件时就调用事件处理程序。有关事件处理程序委托的更多信息,请参见 事件和委托。
示例
private ToolStripMenuItem wholeTable = new ToolStripMenuItem(); private ToolStripMenuItem lookUp = new ToolStripMenuItem(); private ContextMenuStrip strip; private string cellErrorText; private void dataGridView1_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) { cellErrorText = String.Empty; if (strip == null) { strip = new ContextMenuStrip(); lookUp.Text = "Look Up"; wholeTable.Text = "See Whole Table"; strip.Items.Add(lookUp); strip.Items.Add(wholeTable); } e.ContextMenuStrip = strip; } private void wholeTable_Click(object sender, EventArgs e) { dataGridView1.DataSource = Populate("Select * from employees", true); } private DataGridViewCellEventArgs theCellImHoveringOver; private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e) { theCellImHoveringOver = e; } private DataGridViewCellEventArgs cellErrorLocation; private void lookUp_Click(object sender, EventArgs e) { try { dataGridView1.DataSource = Populate("Select * from employees where " + dataGridView1.Columns[theCellImHoveringOver.ColumnIndex].Name + " = '" + dataGridView1.Rows[theCellImHoveringOver.RowIndex]. Cells[theCellImHoveringOver.ColumnIndex].Value + "'", true); } catch (SqlException) { cellErrorText = "Can't look this cell up"; cellErrorLocation = theCellImHoveringOver; } } private void dataGridView1_CellErrorTextNeeded(object sender, DataGridViewCellErrorTextNeededEventArgs e) { if (cellErrorLocation != null) { if (e.ColumnIndex == cellErrorLocation.ColumnIndex && e.RowIndex == cellErrorLocation.RowIndex) { e.ErrorText = cellErrorText; } } } private DataTable Populate(string query, bool resetUnsharedCounter) { if (resetUnsharedCounter) { ResetCounter(); } // Alter the data source as necessary SqlDataAdapter adapter = new SqlDataAdapter(query, new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;" + "Initial Catalog=Northwind;Data Source=localhost")); DataTable table = new DataTable(); table.Locale = System.Globalization.CultureInfo.InvariantCulture; adapter.Fill(table); return table; } private Label count = new Label(); private int unsharedRowCounter; private void ResetCounter() { unsharedRowCounter = 0; count.Text = unsharedRowCounter.ToString(); }