แม้ว่าคำถามนี้จะเก่า แต่คำตอบก็ไม่ถูกต้อง เมนูบริบทมีเหตุการณ์ของตัวเองบน DataGridView มีเหตุการณ์สำหรับเมนูบริบทแถวและเมนูบริบทของเซลล์
เหตุผลที่คำตอบเหล่านี้ไม่ถูกต้องคือไม่ได้อธิบายถึงแผนการดำเนินการที่แตกต่างกัน ตัวเลือกการช่วยการเข้าถึงการเชื่อมต่อระยะไกลหรือการพอร์ต Metro / Mono / Web / WPF อาจไม่ทำงานและแป้นพิมพ์ลัดจะล้มเหลวทันที (Shift + F10 หรือปุ่มเมนูบริบท)
การเลือกเซลล์ด้วยการคลิกเมาส์ขวาจะต้องจัดการด้วยตนเอง การแสดงเมนูบริบทไม่จำเป็นต้องจัดการเนื่องจาก UI จัดการ
สิ่งนี้เลียนแบบวิธีการที่ใช้โดย Microsoft Excel อย่างสมบูรณ์ ถ้ามือถือเป็นส่วนหนึ่งของช่วงที่เลือก, CurrentCell
การเลือกเซลล์ไม่เปลี่ยนแปลงและไม่ไม่ CurrentCell
ถ้ามันไม่ได้เป็นช่วงที่เก่าจะถูกล้างและเซลล์จะถูกเลือกและจะกลายเป็น
หากคุณไม่ชัดเจนในเรื่องนี้CurrentCell
แป้นพิมพ์มีโฟกัสเมื่อคุณกดแป้นลูกศร ไม่ว่าจะเป็นส่วนหนึ่งของSelected
SelectedCells
เมนูบริบทจะแสดงเมื่อคลิกขวาซึ่งจัดการโดย 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;
}
}
}
แป้นพิมพ์ลัดจะไม่แสดงเมนูบริบทตามค่าเริ่มต้นดังนั้นเราจึงต้องเพิ่มเข้าไป
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
}
}
}