DataGrid: On cell validation error other row cells are uneditable/Readonly

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
}

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

Tags:

Wpf

Datagrid