你可以在DataTemplate中使用CollectionViewSource吗?

时间:2010-10-20 15:26:48

标签: wpf data-binding 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>

但这不是......

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

对我来说似乎是这样,但事实并非如此。同样,我们不能将CollectionViewSource放在与数据模板相同的级别,因为每个模板需要有一个实例,因为每个模板都有自己的一组项目(尽管它们都将共享排序标准。)

中号

1 个答案:

答案 0 :(得分:3)

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

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

请注意,我们的实际代码会跟踪我们是否已将排序应用于相关节点,因此不会对每个'Expanded'事件执行此操作,但该代码与此问题无关,因此我省略了它以简洁起见。不过,你应该添加类似的东西。

无论如何,这里是你如何进行每节点排序......

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

}

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

标记