Bien que cette question soit ancienne, les réponses ne sont pas correctes. Les menus contextuels ont leurs propres événements sur DataGridView. Il existe un événement pour le menu contextuel de ligne et le menu contextuel de cellule.
La raison pour laquelle ces réponses ne sont pas correctes est qu'elles ne tiennent pas compte des différents schémas d'exploitation. Les options d'accessibilité, les connexions à distance ou le portage Metro / Mono / Web / WPF peuvent ne pas fonctionner et les raccourcis clavier échoueront vers le bas à droite (Maj + F10 ou touche du menu contextuel).
La sélection de cellule par clic droit de la souris doit être gérée manuellement. L'affichage du menu contextuel n'a pas besoin d'être géré car cela est géré par l'interface utilisateur.
Cela imite complètement l'approche utilisée par Microsoft Excel. Si une cellule fait partie d'une plage sélectionnée, la sélection de cellule ne change pas et non plus CurrentCell
. Si ce n'est pas le cas, l'ancienne plage est effacée et la cellule est sélectionnée et devient CurrentCell
.
Si vous n'êtes pas clair à ce sujet, CurrentCell
c'est là que le clavier a le focus lorsque vous appuyez sur les touches fléchées. Selected
est de savoir si cela fait partie de SelectedCells
. Le menu contextuel s'affichera lors du clic droit comme géré par l'interface utilisateur.
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;
}
}
}
Les raccourcis clavier n'affichent pas le menu contextuel par défaut, nous devons donc les ajouter.
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);
}
}
}
}
J'ai retravaillé ce code pour qu'il fonctionne de manière statique, vous pouvez donc les copier et les coller dans n'importe quel événement.
La clé est à utiliser CellContextMenuStripNeeded
car cela vous donnera le menu contextuel.
Voici un exemple d'utilisation CellContextMenuStripNeeded
où vous pouvez spécifier le menu contextuel à afficher si vous souhaitez en avoir différents par ligne.
Dans ce contexte MultiSelect
est True
et SelectionMode
est FullRowSelect
. Ceci est juste pour l'exemple et non une limitation.
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
}
}
}