你可以在DataTemplate中使用CollectionViewSource吗?

Mar*_*eIV 5 data-binding wpf datatemplate observablecollection collectionviewsource

是否可以在数据模板中显式使用CollectionViewSource?通常我们将CollectionViewSource放在模板旁边的资源中,但我们的模型不允许这样做,因为collectionviewsource的'source'是树中此级别的DataContext的属性,这意味着需要有一个实例在这个水平.把它放在资源的根部就意味着只有一个实例.我们也不能简单地在外层使用分组,因为这些项目不存在,直到您在层次结构中这么远,并且并非所有兄弟都拥有此属性.因此,逻辑上我们在DataTemplate中实例化CollectionViewSource(在这个例子中是HierarchicalDataTemplate,但这是无关紧要的.)

具体来说,我们尝试在此特定节点级别允许特定排序.我们唯一的另一种选择是在ViewModel本身进行排序,但由于我们使用的ObservableCollections本身不支持排序,因此会变得很痛苦.实际上,我们在这个主题上看到的每篇文章都说明你应该正是因为这个原因使用CollectionViewSource,因此这个问题.

例如,这有效......

<HierarchicalDataTemplate x:Key="CategoryTemplate"
    ItemTemplate="{StaticResource TreeViewSymbolTemplate}"
    ItemsSource="{Binding Symbols}">

    <TextBlock Text="{Binding Name}" FontWeight="Bold" />

</HierarchicalDataTemplate>
Run Code Online (Sandbox Code Playgroud)

但这不......

<HierarchicalDataTemplate x:Key="CategoryTemplate"
    ItemTemplate="{StaticResource TreeViewSymbolTemplate}">

    <HierarchicalDataTemplate.ItemsSource>
        <Binding>
            <Binding.Source>
                <CollectionViewSource Source="{Binding Symbols}" />
            </Binding.Source>
        </Binding>
    </HierarchicalDataTemplate.ItemsSource>

    <TextBlock Text="{Binding Name}" FontWeight="Bold" />

</HierarchicalDataTemplate>
Run Code Online (Sandbox Code Playgroud)

在我看来它会像它一样,但事实并非如此.同样,我们不能将CollectionViewSource放在与数据模板相同的级别,因为每个模板需要一个实例,因为每个模板都有自己的一组项目(尽管它们都将共享排序条件.)

中号

Mar*_*eIV 4

好吧......所以这不完全是我想做的,但结果是完全相同的,甚至没有人发表评论,更不用说回答了,因此我把它作为一个。

我们需要这样做的最初原因是进行特定于节点的排序。虽然我们从未让 CollectionViewSource 工作,但我们确实设法将排序直接应用于节点。诀窍是在节点创建时执行此操作,或者像我们正在执行的那样,在节点扩展时执行此操作(我们使用绑定,因此我们不会手动创建节点。)

请注意,我们的实际代码确实会跟踪我们是否已经将排序应用于相关节点,因此不会在每个“扩展”事件上执行该排序,但该代码与此问题无关,因此为了简洁起见,我省略了它。不过,您应该添加类似的内容。

不管怎样,这是你如何进行每节点排序......

private void tvSymbols_Expanded(object sender, RoutedEventArgs e) {

    TreeViewItem node = e.OriginalSource as TreeViewItem;
    if(node==null) return;
    node.Items.SortDescriptions.Clear();
    node.Items.SortDescriptions.Add(new SortDescription("SomeField",      ListSortDirection.Ascending));
    node.Items.SortDescriptions.Add(new SortDescription("SomeOtherField", ListSortDirection.Descending));

}
Run Code Online (Sandbox Code Playgroud)

当然,如果有人仍然弄清楚为什么原始问题的代码不起作用,请让我知道!

标记