Хотя этот вопрос старый, ответы не являются правильными. Контекстные меню имеют свои собственные события в DataGridView.Существует событие для контекстного меню строки и контекстного меню ячейки.
Причина, по которой эти ответы не являются правильными, заключается в том, что они не учитывают разные схемы работы. Параметры доступности, удаленные подключения или перенос между Metro/Mono/Web/WPF могут не работать, а сочетания клавиш спускаются вправо (Shift + F10 или клавиша контекстного меню).
Выбор ячейки правой кнопкой мыши необходимо обрабатывать вручную. Отображать контекстное меню не нужно, поскольку это обрабатывается пользовательским интерфейсом.
Это полностью имитирует подход, используемый Microsoft Excel. Если ячейка является частью выбранного диапазона, выбор ячейки не изменяется, и ни CurrentCell
. Если это не так, старый диапазон очищается и ячейка выбирается и становится CurrentCell
.
Если вы неясны, CurrentCell
- это то, где клавиатура имеет фокус при нажатии клавиш со стрелками. Selected
является ли он частью SelectedCells
. Контекстное меню будет отображаться при щелчке правой кнопкой мыши при работе с пользовательским интерфейсом.
private void dgvAccount_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex != -1 && e.RowIndex != -1 && e.Button == System.Windows.Forms.MouseButtons.Right)
{
DataGridViewCell c = (sender as DataGridView)[e.ColumnIndex, e.RowIndex];
if (!c.Selected)
{
c.DataGridView.ClearSelection();
c.DataGridView.CurrentCell = c;
c.Selected = true;
}
}
}
Сочетания клавиш не показывать контекстное меню по умолчанию, так что мы должны добавить их в.
private void dgvAccount_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.F10 && e.Shift) || e.KeyCode == Keys.Apps)
{
e.SuppressKeyPress = true;
DataGridViewCell currentCell = (sender as DataGridView).CurrentCell;
if (currentCell != null)
{
ContextMenuStrip cms = currentCell.ContextMenuStrip;
if (cms != null)
{
Rectangle r = currentCell.DataGridView.GetCellDisplayRectangle(currentCell.ColumnIndex, currentCell.RowIndex, false);
Point p = new Point(r.X + r.Width, r.Y + r.Height);
cms.Show(currentCell.DataGridView, p);
}
}
}
}
Я переработал этот код, чтобы работать статически, так что вы можете копировать и вставлять их в любом случае.
Ключ должен использовать CellContextMenuStripNeeded
, поскольку это даст вам контекстное меню.
Вот пример, используя CellContextMenuStripNeeded
, где вы можете указать, какое контекстное меню показывать, хотите ли вы иметь разные строки.
В этом контексте MultiSelect
является True
и SelectionMode
является FullRowSelect
. Это просто для примера, а не для ограничения.
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
}
}
}
Правильно! и примечание для вас, var r = dataGridView1.HitTest (e.X, e.Y); r.RowIndex работает WAY BETTER, используя мышь или currentMouseOverRow – 2009-11-12 03:24:09
с использованием .ToString() в string.Format не требуется. – msavara
Этот метод устарел: datagridview обладает свойством: ContextMenu. Контекстное меню будет открыто, как только оператор щелкнет правой кнопкой мыши. Соответствующее событие ContextMenuOpening дает вам возможность решить, что показывать в зависимости от текущей ячейки или выбранных ячеек. См. Один из других ответов –