OrderBy not updating on dependency change

Jun 2, 2010 at 11:25 PM
I'm having a slight issue where the OrderBy clause isn't being respected when a child element is updated. 

 

Assuming I have an object (TestModel) that implements INotifyPropertyChanged and expose a string Name property. I have a BindableLinq query similiar to:

MyItems.Add(new TestModel() { Name = "Ack" }); 
MyItems.Add(new TestModel() { Name = "Bar" }); 
MyItems.Add(new TestModel() { Name = "Car" });
MyBindableItems = MyItems.AsBindable().OrderBy(i => i.Name);

 

When I update one of the underlyling items (say changing 'Ack' to 'ZZZ') the query is never re-executed and my items are no longer sorted properly. After a bit a digging in the code I found that this might be caused by the ItemDependency implementation. Specifically with the SetReevaluateCallback method and the Element_PropertyChange handler as in the current implementation the action given to the SetReevaluateCallback is never retained or invoked. I've updated both methods to the following: 

 

public void SetReevaluateCallback(Action<object> action)
{
    _reevaluateCallback = action;
}

private void Element_PropertyChanged(object element, string propertyPath)
{
    var action = _reevaluateElementCallback;
    if (action != null)
    {
        action(element, propertyPath);
    }

    var tmp = _reevaluateCallback;
    if (tmp != null)
    {
        tmp(element);
    }
}

This seems to do the trick as once the dependent object is modified my query is re-executed and my items are properly sorted. Thoughts?

 

Thanks!

Mar 29, 2011 at 4:56 PM

I had the exact same issue and this change fixed the problem. Thanks

This is clearly a bug with a working fix, yet it hasn't been applied. Is this project completely dead now?

Apr 29, 2011 at 3:49 AM

Its dead because it is a case of over-engineering.  Separate your querying from your binding. it might involve a little more code, but that code will be simple.

Coordinator
Apr 29, 2011 at 6:15 AM

The project is dead because despite being a useful idea, the volume of test scenarios needed to fully implement LINQ in a reactive way is very high, and it never got the take-up it needed to make it worthwhile to maintain. 

Consider the ordered scenario above (assuming it didn't have the bug). How would you do that without Bindable LINQ? 

1. Property changed event on every item in the collection
2. Remember to attach/detach property changed handlers when the collection changes
3. On collection change, ensure added items are inserted in the right place in the ObservableCollection you projected it to 
4. On property change, move items around in the collection (raising a Removed event, followed by an Added event at the right index)

Make sure you use weak event handlers for all of those events as well, so you don't get memory leaks. 

There are UI's that need to do this (I worked on one before building Bindable LINQ - that's where it came from). It is error prone, complicated and verbose code. I'd hate to still be writing it by hand.

Jun 21, 2011 at 1:41 AM

Funny how much work can be created by poor architecture.  In that scenario, in WPF at least, I would just use a CollectionViewSource.  A couple of lines of xaml, job done.