Можете ли вы использовать CollectionViewSource внутри DataTemplate?

Можно ли явно использовать CollectionViewSource внутри шаблона данных? Обычно мы помещаем CollectionViewSource в ресурсы вместе с шаблоном, но наша модель не позволяет этого, потому что «источник» collectionviewsource является свойством DataContext на этом уровне дерева, а это означает, что должен быть экземпляр на этом уровне. Размещение его в корне ресурсов означало бы, что был только один экземпляр. Мы также не можем просто использовать группировку на внешнем уровне, поскольку эти элементы не существуют, пока вы не окажетесь так далеко в иерархии, и не все братья и сестры даже имеют это свойство. Поэтому логически имеет смысл создавать экземпляр CollectionViewSource в DataTemplate (в данном случае 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 на тот же уровень, что и шаблон данных, поскольку для каждого шаблона должен быть один экземпляр, поскольку каждый из них имеет свой собственный набор элементов (хотя все они будут иметь общие критерии сортировки).

M


person Mark A. Donohoe    schedule 20.10.2010    source источник
comment
Очень хотелось бы получить здесь ответ, более подходящий для исходного способа сделать это, или даже если CollectionViewSource находился внутри ресурсной части DataTemplate.   -  person Ingó Vals    schedule 29.12.2010
comment
На самом деле, я нашел еще более простой способ сделать это, который мне очень нравится... Я просто перемещаю CollectionViewSource в преобразователь и использую его для установки возвращаемого значения. На данный момент мы просто «обновляем» один во время связывания, поскольку это все, что нам нужно сделать, но технически мы можем вернуть предварительно гидратированные, на которые у нас есть ссылки, по мере необходимости. Чертовски элегантно, если вы спросите меня, и работает как чемпион!   -  person Mark A. Donohoe    schedule 02.01.2011
comment
Я посмотрю на это. Спасибо.   -  person Ingó Vals    schedule 04.01.2011


Ответы (1)


Хорошо... так что это не совсем то, что я хотел сделать, но результат точно такой же, и никто даже не прокомментировал, не говоря уже об ответе, поэтому я поставил это как один.

Первоначальная причина, по которой нам нужно было это сделать, заключалась в сортировке по узлам. Хотя мы так и не заставили 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));

}

Конечно, если кто-то все еще выясняет, почему исходный код вопроса не работал, дайте мне знать!

отметка

person Mark A. Donohoe    schedule 21.10.2010