Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF DataGrid Validation Bug?

This may be intended functionality, but it sure seems like a bug to me.

I'm using the out-of-the-box WPF DataGrid, bound to an ObservableCollection and attempting to use some validation rules in order to provide nice user feedback. Needless to say there are more issues than I can count, but I'll stick with the immediate.

Here is a summary of the problem:

  1. Bind ItemsSource property to an ObservableCollection<T>
  2. Populate the collection
  3. Edit an item in the grid in a way which will cause a validation error
  4. Programatically remove that item from the ObservableCollection<T>

When these steps are performed, the GridView properly recognizes that the item has been removed from the collection, and removes the row from the grid. However, the Grid is now stuck in an invalid state and no further actions can be performed through the UI on the Grid!

Again, this seems quite like a major bug to me as being able to programmatically remove items from a collection is kind of a big deal.

Has anybody run into this? Any suggestions for how to get around it?

It is worth noting that I have created a separate solution just to isolate this problem, but to answers some questions you might have:

Does your object implement INotifyPropertyChanged? YES

Is this a custom collection? No plain old ObservableCollection<T>

How are you removing items from your collection?

//Find any newly added item and remove it  
var someObject = SomeObjects
             .Where(obj => obj.SomeProperty == SomeValue)
             .First();

SomeObjects.Remove(someObject );

How are you binding your validation rule?

<DataGridTextColumn Header="SomeProperty">
    <DataGridTextColumn.Binding>
        <Binding Path="SomeProperty">
            <Binding.ValidationRules>
                <val:RequiredValidator ValidationStep="ConvertedProposedValue" 
                     ValidatesOnTargetUpdated="True" />
            </Binding.ValidationRules>
        </Binding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>

What does your validation rule look like?

public class RequiredValidator : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if (value == null || String.IsNullOrWhiteSpace(value as String))
            return new ValidationResult(false, "Field is required!");

        return ValidationResult.ValidResult;
    }
}
like image 783
Josh Avatar asked Feb 17 '11 20:02

Josh


2 Answers

I had the same problem and after a long search process I found a solution:

You can create a class which is derived from the DataGrid. There you can access the private properties by reflection. If you now remove an invalid item you can call the function SetGridWritable() and the other values are editable again.

public class MyDataGrid : DataGrid
{
    public void SetGridWritable()
    {
        BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance;
        PropertyInfo cellErrorInfo = this.GetType().BaseType.GetProperty("HasCellValidationError", bindingFlags);
        PropertyInfo rowErrorInfo = this.GetType().BaseType.GetProperty("HasRowValidationError", bindingFlags);
        cellErrorInfo.SetValue(this, false, null);
        rowErrorInfo.SetValue(this, false, null);
    }
}
like image 138
Volker Avatar answered Oct 22 '22 04:10

Volker


I've spent a few hours trying to find out what's going on. Finally, a simple refresh on Items solved the issue. Hope this helps.

YourDataGrid.Items.Refresh();
like image 26
user3870533 Avatar answered Oct 22 '22 04:10

user3870533