Jason D
Jason D

Reputation: 2664

LINQ filtering in IEnumerable property breaks binding

I have a TextBlock in my UI bound to the .Count() extension of a property. I would like to add LINQ filtering to the property, but when I do it breaks the binding.

This works and updates the UI without any problems:

public IEnumerable<Worker> WorkersTest
{
    get
    {
        return DataManager.Data.Workers; 
    }
}

After adding LINQ filtering, WorkersTest does not update the TextBlock, though a MessageBox confirms that the property is being modified. Upon initialization of the data, however, the value displays correctly:

public IEnumerable<Worker> WorkersTest
{
    get
    {
        return DataManager.Data.Workers.Where(w => w.Gender == Gender.Male); 
    }
}

Is there any way to keep the LINQ filtering without breaking the binding?

Update: One thing that I need to clarify is that DataManager.Data.Workers is an ObservableCollection.

From what I can tell, any LINQ operation breaks the binding with the exception of AsEnumerable(), which doesn't have any effect.

Also, in response to Andres' answer, Count() isn't the problem. If I bind this property to a DataGrid, I get the same results. With LINQ, it doesn't update. Without LINQ, it does. Is there any sort of workaround for this, preferably one that doesn't involve ICollectionView or anything of that nature?

Update: Does anybody know if LINQ extensions such as Where return new objects when used? I haven't been able to find any documentation of this online. If this is the case, however, that may be the problem.

Update: I inserted a breakpoint and found some interesting information that may be useful:

Without LINQ:

enter image description here

With LINQ:

enter image description here

enter image description here

Perhaps this can shed some light on what's really going on and hopefully get me closer to the solution.

Would I be correct in assuming that CollectionChanged and PropertyChanged being null is the source of the problem? If so, what can I do to fix that?

Upvotes: 2

Views: 596

Answers (2)

Euphoric
Euphoric

Reputation: 12849

Your problem stems from not understanding observable collections. DataManager.Data.Workers is ObservableCollection or something similar. It means, it will raise events when items are added/removed. The UI can then listen to those events and update appropriately.

LINQ doesn't understand anything about observable collections. It just reads and transforms data into new collection, one time, one way. So using LINQ for your filtering is not going to work. Or at least not without some kind of hack.

There are definitely few ways, like Filtering an ObservableCollection? or Sorts and filters on ObservableCollection. But nothing so easy as just throwing a simple LINQ on it. Or maybe Reactive Extensions could help you here. But I never used it so I don't know how easy would it be to setup a filtering observable collection.

Upvotes: 1

Andres Rebolledo
Andres Rebolledo

Reputation: 57

Try adding .ToList() at the end of your Where clause.

return DataManager.Data.Workers.Where(w => w.Gender == Gender.Male).ToList(); 

Binding to methods isn't allowed so what is probably happening is you are binding to the Count property instead of method. List contains the Count property whereas IEnumerable does not.

Upvotes: 0

Related Questions