Meskipun pertanyaan ini sudah tua, jawabannya tidak tepat. Menu konteks memiliki acara mereka sendiri di DataGridView. Ada acara untuk menu konteks baris dan menu konteks sel.
Alasan mengapa jawaban ini tidak tepat adalah karena tidak memperhitungkan skema operasi yang berbeda. Opsi aksesibilitas, koneksi jarak jauh, atau port Metro / Mono / Web / WPF mungkin tidak berfungsi dan pintasan keyboard turun ke kanan gagal (tombol Shift + F10 atau Menu Konteks).
Pemilihan sel pada klik kanan mouse harus ditangani secara manual. Menampilkan menu konteks tidak perlu ditangani karena ini ditangani oleh UI.
Ini sepenuhnya meniru pendekatan yang digunakan oleh Microsoft Excel. Jika sel adalah bagian dari rentang yang dipilih, pemilihan sel tidak berubah dan tidak juga CurrentCell
. Jika tidak, rentang lama dihapus dan sel dipilih dan menjadi CurrentCell
.
Jika Anda tidak jelas tentang ini, di CurrentCell
mana keyboard memiliki fokus saat Anda menekan tombol panah. Selected
adalah apakah itu bagian dari SelectedCells
. Menu konteks akan ditampilkan pada klik kanan seperti yang ditangani oleh UI.
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;
}
}
}
Pintasan keyboard tidak menampilkan menu konteks secara default, jadi kita harus menambahkannya.
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);
}
}
}
}
Saya telah mengerjakan ulang kode ini agar berfungsi secara statis, sehingga Anda dapat menyalin dan menempelkannya ke acara apa pun.
Kuncinya adalah menggunakan CellContextMenuStripNeeded
karena ini akan memberi Anda menu konteks.
Berikut adalah contoh penggunaan di CellContextMenuStripNeeded
mana Anda dapat menentukan menu konteks mana yang akan ditampilkan jika Anda ingin memiliki menu yang berbeda per baris.
Dalam konteks ini MultiSelect
adalah True
dan SelectionMode
adalah FullRowSelect
. Ini hanya untuk contoh dan bukan batasan.
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
}
}
}