Anche se questa domanda è vecchia, le risposte non sono corrette. I menu contestuali hanno i propri eventi su DataGridView. C'è un evento per il menu contestuale della riga e il menu contestuale della cella.
Il motivo per cui queste risposte non sono corrette è che non tengono conto di schemi operativi diversi. Le opzioni di accessibilità, le connessioni remote o il porting Metro / Mono / Web / WPF potrebbero non funzionare e le scorciatoie da tastiera non funzioneranno correttamente (Maiusc + F10 o tasto Menu contestuale).
La selezione delle celle al clic destro del mouse deve essere gestita manualmente. La visualizzazione del menu contestuale non deve essere gestita poiché viene gestita dall'interfaccia utente.
Questo imita completamente l'approccio utilizzato da Microsoft Excel. Se una cella fa parte di un intervallo selezionato, la selezione della cella non cambia e nemmeno lo fa CurrentCell
. In caso contrario, il vecchio intervallo viene cancellato e la cella viene selezionata e diventa CurrentCell
.
Se non sei chiaro su questo, CurrentCell
è dove la tastiera è attiva quando premi i tasti freccia. Selected
è se fa parte di SelectedCells
. Il menu contestuale verrà visualizzato al clic destro come gestito dall'interfaccia utente.
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;
}
}
}
Le scorciatoie da tastiera non mostrano il menu contestuale per impostazione predefinita, quindi dobbiamo aggiungerle.
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);
}
}
}
}
Ho rielaborato questo codice in modo che funzioni in modo statico, quindi puoi copiarlo e incollarlo in qualsiasi evento.
La chiave è usare CellContextMenuStripNeeded
poiché questo ti darà il menu contestuale.
Ecco un esempio in CellContextMenuStripNeeded
cui è possibile specificare quale menu di scelta rapida mostrare se si desidera averne di diversi per riga.
In questo contesto MultiSelect
è True
ed SelectionMode
è FullRowSelect
. Questo è solo un esempio e non una limitazione.
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
}
}
}