In my wpf datagrid I have implemented validation using IDataErrorInfo
. When there is a error in a cell, cells in other rows become ReadOnly. To me this makes sense, but business wants to be able to change other row cells without fixing the error i.e. in some scenarios let users make a mess and, poor developer's life miserable.
I have tried resetting HasCellValidationError
to false but it did not fix it. I'll very highly appreciate any feedback/suggestion on this issue.
BindingFlags bf = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance;
PropertyInfo inf = myDataGrid.GetType().GetProperty("HasCellValidationError", bf);
if (inf != null)
{
inf.SetValue(myDataGrid, false, null);
}
Gazi's answer does the trick with regards to keeping the grid editable. However, while with this implementation users can continue to edit other fields, the values of these additional changes will not be written to your model and no further validations can be done. The problem becomes apparent when further user changes would result in additional Validation Errors. These will not be raised, because source update and validation won't happen.
To overcome this a similar implementation like yours needs to be done inside OnExecutedCommitEdit
. See the answer to this multiple DataGrid row validation question
Found a solution by overriding the OnCanExecuteBeginEdit method of the datagrid. See the code below and so far testers have not complaint.
/// <summary>
/// This class overrides the OnCanExecuteBeginEdit method of the standard grid
/// </summary>
public partial class DataGrid : System.Windows.Controls.DataGrid
{
/// <summary>
/// This method overrides the
/// if (canExecute && HasRowValidationError) condition of the base method to allow
/// ----entering edit mode when there is a pending validation error
/// ---editing of other rows
/// </summary>
/// <param name="e"></param>
protected override void OnCanExecuteBeginEdit(System.Windows.Input.CanExecuteRoutedEventArgs e)
{
bool hasCellValidationError = false;
bool hasRowValidationError = false;
BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance;
//Current cell
PropertyInfo cellErrorInfo = this.GetType().BaseType.GetProperty("HasCellValidationError", bindingFlags);
//Grid level
PropertyInfo rowErrorInfo = this.GetType().BaseType.GetProperty("HasRowValidationError", bindingFlags);
if (cellErrorInfo != null) hasCellValidationError = (bool)cellErrorInfo.GetValue(this, null);
if (rowErrorInfo != null) hasRowValidationError = (bool)rowErrorInfo.GetValue(this, null);
base.OnCanExecuteBeginEdit(e);
if (!e.CanExecute && !hasCellValidationError && hasRowValidationError )
{
e.CanExecute = true;
e.Handled = true;
}
}
#region baseOnCanExecuteBeginEdit
//protected virtual void OnCanExecuteBeginEdit(CanExecuteRoutedEventArgs e)
//{
// bool canExecute = !IsReadOnly && (CurrentCellContainer != null) && !IsEditingCurrentCell && !IsCurrentCellReadOnly && !HasCellValidationError;
// if (canExecute && HasRowValidationError)
// {
// DataGridCell cellContainer = GetEventCellOrCurrentCell(e);
// if (cellContainer != null)
// {
// object rowItem = cellContainer.RowDataItem;
// // When there is a validation error, only allow editing on that row
// canExecute = IsAddingOrEditingRowItem(rowItem);
// }
// else
// {
// // Don't allow entering edit mode when there is a pending validation error
// canExecute = false;
// }
// }
// e.CanExecute = canExecute;
// e.Handled = true;
//}
#endregion baseOnCanExecuteBeginEdit
}
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