如何将Wpf的HierarchicalDataTemplate的ItemsSource绑定到字典中的CollectionViewSource?

4
我将尝试展示一个Wpf Treeview,并使用CollectionViewSource对其进行排序。
目前,除了使用我的资源字典中的以下代码进行排序之外,一切都正常:
<HierarchicalDataTemplate DataType="{x:Type books:Container}" ItemsSource="{Binding Path=Items}">
    <nav:ContainerControl />
</HierarchicalDataTemplate>

如何更改HierarchicalDataTemplate的语法,以绑定到CollectionViewSource,该CollectionViewSource反过来从Items属性中提取数据?

我尝试了Bea Stollnitz博客上发布的代码的各种变体,但没有成功。我无法弄清楚如何设置CollectionViewSource的源。


好问题,我也正想问呢。谢谢! :-) - Robert Fraser
2个回答

7

让我说一下,我不喜欢我的解决方案,但它确实有效。也许一个WPF大师会用更好的替代方法启发我们。当然,如果您在视图后面使用ViewModel,您可以简单地在ViewModel中使用CollectionView包装模型的Items属性就行了。

但这里有另一个解决方案。基本上,您的HierarchicalDataTemplate可以保持不变,只需在绑定中添加一个转换器即可。我实现了以下转换器并相应地更改了XAML。

<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;
    }
}

然而,这个解决方案会引起一个小问题。在 Visual Studio 输出窗口中会反复打印出警告信息:“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')”不过,在 MSDN 论坛上有一位微软员工表示,这个警告可以安全地忽略。 - awx
那个错误听起来像是来自TreeViewItem的默认模板,而不是你的问题所涉及的绑定。 - Josh
1
我相当喜欢你的解决方案。就我而言,唯一的缺陷是Instance是公开可写的,并且您硬编码了排序属性,而您可以将ConverterParameter转换为字符串并使其成为通用解决方案。 - Peter Wone

0

我按照您建议的方法用 ListCollectionView 包装了 Items 集合:

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;
        }
    }

我有没有漏掉什么?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接