Search code examples
c#wpftreeviewcollectionviewsourcelistcollectionview

CollectionView live sorting callback


I have a TreeView that uses a ListCollectionView with a custom IComprarer and live shaping to order its children. When the currently selected TreeViewItem is re-sorted in the view, I'd like the TreeView to automatically scroll to the TreeViewItem's new position. However, I can't find a way to be notified when the ListCollectionView applies a new sort, and the behavior I want doesn't seem to be built into the TreeViewControl.

Is there a way I can be notified when the ListCollectionView recomputes its sort order?


Solution

  • I believe the event CollectionChanged is what you need. You can do something like this:

    ((ICollectionView)yourListCollectionView).CollectionChanged += handler;
    

    The reason we have to cast here is CollectionChanged is implemented as the member of INotifyPropertyChanged (ICollectionView inherits from this interface), source code here:

    event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
    {
        add {
                CollectionChanged += value;
        }
        remove {
                CollectionChanged -= value;
        }
    }
    

    This implementation is explicit. So the event is hidden from normal access as a public member. To expose that member, you can either cast the instance to ICollectionView or INotifyPropertyChanged.

    . When implementing an interface explicitly, you have to explicitly cast the instance to that interface before being able to access the interface members.

    Example about implementing interface:

    public interface IA {
       void Test();
    }
    //implicitly implement
    public class A : IA {
       public void Test() { ... }
    }
    var a = new A();
    a.Test();//you can do this
    
    
    //explicitly implement
    public class A : IA {
       void IA.Test() { ... } //note that there is no public and the interface name 
                              // is required
    }
    var a = new A();
    ((IA)a).Test(); //this is how you do it.