I would need an event that fires when the current row of a System.Windows.Forms.DataGridView
is going to be changed and which allows me to cancel this change, e.g. by setting the Cancel-property of the EventArgs to true.
I know about the CurrentCellChanged
(the row has already changed when the event is called) and the RowLeave
(no possibility to cancel the leave-operation) events, but neither provide what I would need. I also tried to use the RowValidating
event, but this event is also called when the row is just going to be validated (without the intention to leave it), for example when I call <ParentForm>.Validate()
, which leads to many confusions.
Is there any other possibility or a clean(er) solution to get the desired behaviour?
The event. stopPropagation() method stops the bubbling of an event to parent elements, preventing any parent event handlers from being executed. Tip: Use the event. isPropagationStopped() method to check whether this method was called for the event.
The preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur. For example, this can be useful when: Clicking on a "Submit" button, prevent it from submitting a form.
preventDefault() prevents the browsers default behaviour, but does not stop the event from bubbling up the DOM. The event. stopPropagation() prevents the event from bubbling up the DOM, but does not stop the browsers default behaviour.
As you probably might have already worked out based on the simple explanation above: the opposite of event. preventDefault() is nothing. You just don't prevent the event, by default the browser will allow the event if you are not preventing it.
Just Ran into a similar issue and after many attempts my only work around was to use "Enter and Leave" to know when the form was NotActive to avoid Validating - Luckily the firing order was before the row\col level events
HTH - Mike
private bool IsActive = false;
private void dgbList_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
if (IsActive)
{
if (Do_I_NeedTo_Cancel)
e.Cancel = true;
}
}
private void dgList_Leave(object sender, EventArgs e)
{
IsActive = false;
}
private void dgList_Enter(object sender, EventArgs e)
{
IsActive = true;
}
I think your best option is to use RowValidating with a bool condition to check if you call .Validate().
EDIT
Per your last comment, why not add a check for dataGridView.IsCurrentRowDirty
?
For example:
private void dataGridView1_RowValidating(object sender, DataGridViewCellCancelEventArgs e) {
if (dataGridView1.IsCurrentRowDirty) {
if (dataCheck())
if (MessageBox.Show("Ok?", "Save?", MessageBoxButtons.YesNoCancel) == DialogResult.Cancel) {
e.Cancel = true;
}
}
}
If there is no dirty data, no matter who calls the validation the dataCheck won't be made and the messageBox will not appear.
EDIT
You can replace the 'if' clauses with any check you want, including one for dataGridView2.
You can also extend the dataGridView control if you have very complicated requirements.
EDIT
I now understand your requirement. I don't think there is a quick and clean solution. I would use the SelectionChanged event and there set the logic to prevent the change. Something like:
//rember the selection of the index
private int _currentIndex;
private bool _rollingBackSelection;
private void SelectionChanged(...){
//when changing back to the selection in dgv1 prevent dgv2 check
if (_rollingBackSelection) {
_rollingBackSelection = false;
return;
}
if (dgv2IsDirty()) {
var result = MessageBox.Show("Ok?", "Save?", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Cancel) {
_rollingBackSelection = true;
//rollback to the previous index
dgv1.Rows[_currentIndex].Selected = true;
return;
}
if (result == DialogResult.Yes)
dgv2Save();
dgv2Load();
_currentIndex = dgv1.SelectedRows[0].Index;
}
}
I think something like above is your best shot.
After trying lots of different things I came to the solution that the easiest and (for me) best working solution would be to check which control is focused in the RowValidating
event of the DataGridView
. This solution addresses exactly the problem I had: the RowValidating
event was thrown by clicking other buttons for example. There are still some special cases which cause the RowValidating
event to arise even if the current row isn't changing (sorting the DataGridView
by clicking a column header, for example) but I think I can live with this minor issues. Maybe a future version of .NET will implement a DataGridView
with a RowLeaving
event which can be cancelled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With