var relativeMousePosition = DataGridView1.PointToClient(Cursor.Position);
this.ContextMenuStrip1.Show(DataGridView1, relativeMousePosition);
整个事件处理程序如下所示:
private void DataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
// Ignore if a column or row header is clicked
if (e.RowIndex != -1 && e.ColumnIndex != -1)
{
if (e.Button == MouseButtons.Right)
{
DataGridViewCell clickedCell = (sender as DataGridView).Rows[e.RowIndex].Cells[e.ColumnIndex];
// Here you can do whatever you want with the cell
this.DataGridView1.CurrentCell = clickedCell; // Select the clicked cell, for instance
// Get mouse position relative to the vehicles grid
var relativeMousePosition = DataGridView1.PointToClient(Cursor.Position);
// Show the context menu
this.ContextMenuStrip1.Show(DataGridView1, relativeMousePosition);
}
}
}
private void dgvAccount_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
if (e.RowIndex == -1 || e.ColumnIndex == -1)
return;
bool isPayment = true;
bool isCharge = true;
foreach (DataGridViewRow row in dgv.SelectedRows)
{
if ((string)row.Cells["P/C"].Value == "C")
isPayment = false;
else if ((string)row.Cells["P/C"].Value == "P")
isCharge = false;
}
if (isPayment)
e.ContextMenuStrip = cmsAccountPayment;
else if (isCharge)
e.ContextMenuStrip = cmsAccountCharge;
}
private void cmsAccountPayment_Opening(object sender, CancelEventArgs e)
{
int itemCount = dgvAccount.SelectedRows.Count;
string voidPaymentText = "&Void Payment"; // to be localized
if (itemCount > 1)
voidPaymentText = "&Void Payments"; // to be localized
if (tsmiVoidPayment.Text != voidPaymentText) // avoid possible flicker
tsmiVoidPayment.Text = voidPaymentText;
}
private void cmsAccountCharge_Opening(object sender, CancelEventArgs e)
{
int itemCount = dgvAccount.SelectedRows.Count;
string deleteChargeText = "&Delete Charge"; //to be localized
if (itemCount > 1)
deleteChargeText = "&Delete Charge"; //to be localized
if (tsmiDeleteCharge.Text != deleteChargeText) // avoid possible flicker
tsmiDeleteCharge.Text = deleteChargeText;
}
private void tsmiVoidPayment_Click(object sender, EventArgs e)
{
int paymentCount = dgvAccount.SelectedRows.Count;
if (paymentCount == 0)
return;
bool voidPayments = false;
string confirmText = "Are you sure you would like to void this payment?"; // to be localized
if (paymentCount > 1)
confirmText = "Are you sure you would like to void these payments?"; // to be localized
voidPayments = (MessageBox.Show(
confirmText,
"Confirm", // to be localized
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2
) == DialogResult.Yes);
if (voidPayments)
{
// SQLTransaction Start
foreach (DataGridViewRow row in dgvAccount.SelectedRows)
{
//do Work
}
}
}
private void tsmiDeleteCharge_Click(object sender, EventArgs e)
{
int chargeCount = dgvAccount.SelectedRows.Count;
if (chargeCount == 0)
return;
bool deleteCharges = false;
string confirmText = "Are you sure you would like to delete this charge?"; // to be localized
if (chargeCount > 1)
confirmText = "Are you sure you would like to delete these charges?"; // to be localized
deleteCharges = (MessageBox.Show(
confirmText,
"Confirm", // to be localized
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2
) == DialogResult.Yes);
if (deleteCharges)
{
// SQLTransaction Start
foreach (DataGridViewRow row in dgvAccount.SelectedRows)
{
//do Work
}
}
}
对于上下文菜单的位置,y 发现问题,我需要一个 it 来相对于 DataGridView,并且我需要使用的事件给出了相对于单元格单击的位置。我还没有找到更好的解决方案,所以我在 commons 类中实现了这个函数,所以我在任何需要的地方调用它。
它经过了很好的测试,我希望你能发现它的用处。
/// <summary>
/// When DataGridView_CellMouseClick ocurs, it gives the position relative to the cell clicked, but for context menus you need the position relative to the DataGridView
/// </summary>
/// <param name="dgv">DataGridView that produces the event</param>
/// <param name="e">Event arguments produced</param>
/// <returns>The Location of the click, relative to the DataGridView</returns>
public static Point PositionRelativeToDataGridViewFromDataGridViewCellMouseEventArgs(DataGridView dgv, DataGridViewCellMouseEventArgs e)
{
int x = e.X;
int y = e.Y;
if (dgv.RowHeadersVisible)
x += dgv.RowHeadersWidth;
if (dgv.ColumnHeadersVisible)
y += dgv.ColumnHeadersHeight;
for (int j = 0; j < e.ColumnIndex; j++)
if (dgv.Columns[j].Visible)
x += dgv.Columns[j].Width;
for (int i = 0; i < e.RowIndex; i++)
if (dgv.Rows[i].Visible)
y += dgv.Rows[i].Height;
return new Point(x, y);
}
// somewhere in your code
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Option1"));
cm.MenuItems.Add(new MenuItem("Option2"));
分配到 DataGridView
myDataView.ContextMenu = cm;
在不更改 Selected单元格的情况下从单元格中获取数据
private void myDataView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
string myData = myDataView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
// Now ADD the captured DATA to the ContextMenu
cm.MenuItems.Add(new MenuItem("myData"));
// OR if you are doing it by the designer and YOU ALREADY have an Item
// you can simply change the name of it in the designer page to your
// desired one and then just change the Text of it
MenuItem_BTN.Text = "$Properties of {myData}";
}
}