My application has a datagridview with a RowValidating event handler. If I set ErrorText
in RowValidating, it correctly disallows left-clicking on other rows and other controls, but if I have a ContextMenuStrip assigned to another control, the ContextMenuStrip remains active. The user can right-click on the control with the context menu, select a menu item, and the menu events fire.
I've tried all sorts of event handling, but the RowValidating event doesn't fire before the menu is presented, so I can't just disable the context menu in RowValidating. I could perhaps disable the context menu whenever the user is touching any part of the grid, but that has other pitfalls...
I've looked and I don't see any existing writeup on a Microsoft defect or a workaround, or even anyone else encountering the error, so I'm not sure what I could be doing wrong.
Simplified example:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.menuItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.textBox1 = new System.Windows.Forms.TextBox();
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1});
this.dataGridView1.RowValidating += new System.Windows.Forms.DataGridViewCellCancelEventHandler(this.dataGridView1_RowValidating);
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.menuItemToolStripMenuItem});
this.menuItemToolStripMenuItem.Text = "Menu Item";
this.textBox1.ContextMenuStrip = this.contextMenuStrip1;
this.Controls.Add(this.textBox1);
this.Controls.Add(this.dataGridView1);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem menuItemToolStripMenuItem;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
private void dataGridView1_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
if (!RowValid(dataGridView1.Rows[e.RowIndex]))
{
dataGridView1.Rows[e.RowIndex].ErrorText = "Value must be 5";
e.Cancel = true;
}
else
{
dataGridView1.Rows[e.RowIndex].ErrorText = string.Empty;
e.Cancel = false;
}
}
private bool RowValid(DataGridViewRow row)
{
return string.Equals(row.Cells[0].Value, "5");
}
For reference, these are the events fired in order, note validation does not occur prior to menu opening:
dataGridView1_Enter
dataGridView1_RowEnter
dataGridView1_CellEnter
dataGridView1_CellBeginEdit
contextMenuStrip1_Opening
Handle ToolStripDropDown.Opening event, determine if the context menu should showup or not by setting
e.Cancel
. Or you can disable the menu item instead.