4

I'm trying to display a Wpf Treeview with items sorted by a CollectionViewSource.

Currently, everything is working except sorting using this code in my resource dictionary:

<HierarchicalDataTemplate DataType="{x:Type books:Container}" ItemsSource="{Binding Path=Items}">
    <nav:ContainerControl />
</HierarchicalDataTemplate>

What would be the syntax for changing the HierarchicalDataTemplate to bind to a CollectionViewSource that in turn pulls from the Items property?

I've tried variations of the code posted on Bea Stollnitz's blog with no success. I can't figure out how to set the source of the CollectionViewSource.

awx
  • 97
  • 2
  • 6

2 Answers2

7

Well let me just say that I hate my proposed solution, but it does work. Perhaps a WPF guru will enlighten us both with a better alternative. Of course if you were using a ViewModel behind your view, you could simply wrap the Items property of the model with a CollectionView in the ViewModel and be done with it.

But here's another solution. Basically, your HierarchicalDataTemplate can stay as is except you would add a Converter to the Binding. I implemented the following converter and changed the XAML accordingly.

<HierarchicalDataTemplate DataType="{x:Type books:Container}"
    ItemsSource="{Binding Items, Converter={x:Static local:CollectionViewConverter.Instance}}">
    <nav:ContainerControl />
</HierarchicalDataTemplate>

CollectionViewConverter.cs

public class CollectionViewConverter : IValueConverter
{

    public CollectionViewConverter() {}

    static CollectionViewConverter(){
        Instance = new CollectionViewConverter();
    }

    public static CollectionViewConverter Instance {
        get;
        set;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var view = new ListCollectionView((System.Collections.IList)value);
        view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
        return view;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // not really necessary could just throw notsupportedexception
        var view = (CollectionView)value;
        return view.SourceCollection;
    }
}
Josh
  • 68,005
  • 14
  • 144
  • 156
  • This solution is causing one minor issue however. This warning is printed in the Visual Studio Output window repeatedly. "System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'TreeViewItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')" A MS guy in the MSDN groups says it can safely be ignored however. – awx Jan 20 '10 at 06:33
  • That error sounds like it's coming from the default template for TreeViewItem, not the binding that your question deals with. – Josh Jan 20 '10 at 06:44
  • 1
    I rather like your solution. So far as I'm concerned, the only flaws are that Instance is publicly writable and you hardcoded the sort property when you could cast ConverterParameter as a string and make this a general solution. – Peter Wone Oct 27 '11 at 04:58
0

I did as you suggested and wrapped the Items collection with a ListCollectionView:

private SortDescription _ItemsLcvSortDesc;
    private SortDescription ItemsLcvSortDesc
    {
        get
        {
            if (_ItemsLcvSortDesc == null)
                _ItemsLcvSortDesc = new SortDescription("SortOrder", ListSortDirection.Ascending);
            return _ItemsLcvSortDesc;
        }
    }

    private ListCollectionView _ItemsLcv;
    public ListCollectionView ItemsLcv
    {
        get
        {
            if (_ItemsLcv == null)
                _ItemsLcv = CollectionViewSource.GetDefaultView(Items) as ListCollectionView;
            _ItemsLcv.SortDescriptions.Add(ItemsLcvSortDesc);
            return _ItemsLcv;
        }
    }

Did I miss anything?

awx
  • 97
  • 2
  • 6