Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

wpf

datagrid

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);
}
like image 620
Gazi Avatar asked Nov 04 '10 01:11

Gazi


2 Answers

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

like image 142
knilch Avatar answered Oct 19 '22 04:10

knilch


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
}
like image 23
Gazi Avatar answered Oct 19 '22 05:10

Gazi