你能在DataTemplate内使用CollectionViewSource吗?

7
在数据模板内明确使用CollectionViewSource是否可行?通常我们会将CollectionViewSource与模板放在资源中,但是我们的模型不允许这样做,因为CollectionViewSource的“源”是DataContext在树的此级别上的属性,这意味着需要在此级别上有一个实例。将其放在资源的根目录中将意味着只有一个实例。我们也不能简单地在外部级别上使用分组,因为这些项直到您到达这个层次才存在,并且并非所有同级甚至都具有此属性。因此,在DataTemplate(在这种情况下是HierarchicalDataTemplate,但这无关紧要)中实例化CollectionViewSource是合乎逻辑的。

具体来说,我们试图允许在此特定节点级别上进行特定排序。我们唯一的选择是在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放在与数据模板相同的级别上,因为每个模板都需要一个实例,因为每个模板都有自己的项目集(尽管它们将共享排序标准)。

真的很想得到一个更适合原始方法的答案,甚至如果CollectionViewSource在DataTemplate的Resource部分内。 - Ingó Vals
1
实际上,我发现了一种更简单的方法来做到这一点,我真的很喜欢... 我只是将CollectionViewSource移动到一个转换器中,并使用它来设置返回值。目前我们只是在绑定时创建一个新的,因为这是我们需要做的所有事情,但从技术上讲,我们可以根据需要返回预先填充好的引用。如果你问我,这个方法非常棒,而且像个冠军一样工作! - Mark A. Donohoe
1个回答

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

}

当然,如果有人还能解决原问题代码为什么不起作用的问题,请告诉我!
马克

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