2
votes

I have a view into which some quantity (zero or more) of Entity objects are loaded from somewhere external (file, web service, etc). I need the user to be able to edit the loaded entities as well as add new rows before they are all saved in one transaction. At the time they are loaded, the entities are generally not valid; they all require user input before they are ready to be persisted. In order to accomplish this, the view contains a WPF DataGrid whose ItemsSource is a BindingList<Entity>, and my Entity class implements IDataErrorInfo to provide the per-cell error messages to be displayed in tooltips in the grid.

The default behavior for DataGrid when the currently-selected cell has validation errors is to disable editing all other rows as well as adding new rows until the issue is resolved. This is not what I want; the user should be able to do what it takes to make the rows valid in whatever order he/she chooses. I can make existing rows editable by inheriting from DataGrid and overriding OnCanExecuteBeginEdit:

class EditableDataGrid : DataGrid
{
    protected override void OnCanExecuteBeginEdit(CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
        e.Handled = true;
    }
}

This works as desired to allow editing rows that already exist. But it still does not enable adding new rows. Is there a way to override this behavior? Or do I need to create custom "validation"-handling logic outside of what WPF provides so that everything is always valid as far as the framework is concerned, just to avoid triggering unwanted limitations in the provided controls?

Update: This behavior also seems to be the source of another issue I intermittently face with the DataGrid. I would like the user to be able to save the work-in-progress and work on a different "batch" of Entities in the meantime. In this case, I clear the grid to create a fresh slate for the user. However, if the DataGrid has already decided not to create the new placeholder row at the bottom due to validation errors, there will still be no placeholder row when the grid is cleared, and the user has no way to continue. I can try to find another override hack for this, but I would really prefer to fix the underlying behavior (i.e. stop blocking adds/edits when the current data is "invalid").

1

1 Answers

0
votes

I had the same issue and was able to fix it by overriding the OnExecutedCommitEdit as well. In the override, call the base implementation to do the commit. Then, if the editing unit is cell mode, then also "cancel" the edit. If the cell commit succeeded, this will simply have no effect. If it did not succeed, this will cancel the invalid input and allow editing on other rows and make the new row show back up. The side effect is that if the user enters invalid data in a cell, it will disappear when committing the edit. IMO this is better than the data grid getting "stuck".

    protected override void OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
    {
        base.OnExecutedCommitEdit(e);
        if (e.Parameter is DataGridEditingUnit unit && unit == DataGridEditingUnit.Cell)
        {
            CancelEdit(unit);
        }
    }