Chociaż to pytanie jest stare, odpowiedzi nie są poprawne. Menu kontekstowe mają własne zdarzenia w DataGridView. Istnieje zdarzenie dla menu kontekstowego wiersza i menu kontekstowego komórki.
Powodem, dla którego te odpowiedzi nie są właściwe, jest to, że nie uwzględniają one różnych schematów działania. Opcje ułatwień dostępu, połączenia zdalne lub portowanie Metro / Mono / Web / WPF mogą nie działać, a skróty klawiaturowe nie działają poprawnie (Shift + F10 lub klawisz Menu kontekstowe).
Wybór komórek prawym przyciskiem myszy musi być obsługiwany ręcznie. Wyświetlanie menu kontekstowego nie musi być obsługiwane, ponieważ obsługuje to interfejs użytkownika.
To całkowicie naśladuje podejście stosowane przez Microsoft Excel. Jeśli komórka należy do wybranego zakresu, zaznaczenie komórek nie zmienia się i nie CurrentCell
. Jeśli tak nie jest, stary zakres jest czyszczony, a komórka jest zaznaczona i staje się CurrentCell
.
Jeśli nie masz pewności co do tego, CurrentCell
jest to miejsce, w którym klawiatura ma fokus po naciśnięciu klawiszy strzałek. Selected
jest to, czy jest częścią SelectedCells
. Menu kontekstowe pojawi się po kliknięciu prawym przyciskiem myszy, tak jak jest obsługiwane przez interfejs użytkownika.
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;
}
}
}
Skróty klawiaturowe domyślnie nie wyświetlają menu kontekstowego, więc musimy je dodać.
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);
}
}
}
}
Przeprojektowałem ten kod, aby działał statycznie, więc możesz skopiować i wkleić go do dowolnego wydarzenia.
Kluczem jest użycie, CellContextMenuStripNeeded
ponieważ da ci to menu kontekstowe.
Oto przykład, w CellContextMenuStripNeeded
którym możesz określić, które menu kontekstowe ma być wyświetlane, jeśli chcesz mieć różne menu w wierszu.
W tym kontekście MultiSelect
jest True
i SelectionMode
jest FullRowSelect
. To tylko przykład, a nie ograniczenie.
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
}
}
}