Search code examples
wpfmvvmwpfdatagrid

WPF DataGrid - how to stop user proceeding if there are invalid cells? (MVVM)


I'm implementing edit functionality in my DataGrid. The CellEditingTemplate of a typical cell looks something like this:-

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox Grid.Column="0" 
                 Text="{Binding Concentration, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=LostFocus}"
                 Validation.ErrorTemplate="{StaticResource errorTemplate}" />
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

In this example there is a TextBox bound to a property called "Concentration", which is a property of type double, with validation to ensure that it falls within a given range. The models that are being bound to the grid implement IDataErrorInfo by the way.

The problem is, although the error template highlights the cell when an invalid value is entered, there is nothing to stop me from moving focus away from that cell (or row). What's the preferred approach for handling validation with data grid editing? I wondered if I could prevent the user from leaving the cell until a valid value was entered, but that could be dangerous - they wouldn't be able to do anything (even close the app) until a valid value had been entered.

Another option might be to prevent the user from proceeding if the datagrid contains any invalid rows. But what's the best way to test this? IDataErrorInfo doesn't provide an "IsValid" property that I can examine on each of the rows' models.

Lastly I could just revert the model's property back to its previous "good" value (or a default value) if the user enters something invalid.

Any suggestions? I'm using MVVM by the way.


Solution

  • I use this to see if IDataerrorInfo has any errors for the object, a small snippet of the implementation:

    protected Dictionary<string, string> _propertyErrors = new Dictionary<string, string>();
    public bool HasErrors {
        get { return (_propertyErrors.Count) > 0; }
    }
    

    Then I can handle the logic for what to do after evaluating this property. Do you want to prevent navigation, closing app, etc. Then you need to evaluate for errors from that code and then cancel that action.