WPF HiercharchicalDataTemplate.DataType: как реагировать на интерфейсы?

Проблема

У меня есть коллекция IThing, и я хотел бы создать HierarchicalDataTemplate для TreeView. Простой DataType = {x:Type local:IThing}, конечно, не работает, вероятно, потому, что создатели WPF не хотели справляться с возможной двусмысленностью.

Поскольку это должно обрабатывать IThing из разных источников одновременно, упоминание реализующего класса не может быть и речи.

Текущее решение

На данный момент я использую ViewModel, который проксирует IThing через конкретную реализацию:

public interface IThing {
    string SomeString { get; }
    ObservableCollection<IThing> SomeThings { get; }
    // many more stuff
}

public class IThingViewModel
{
     public IThing Thing { get; }
     public IThingViewModel(IThing it) { this.Thing = it; }
}

<!-- is never applied -->
<HierarchicalDataTemplate DataType = "{x:Type local:IThing}">

<!-- is applied, but looks strange -->
<HierarchicalDataTemplate
    DataType = "{x:Type local:IThingViewModel}"
    ItemsSource = "{Binding Thing.SomeThings}">
    <TextBox Text = "{Binding Thing.SomeString}"/>
</HierarchicalDataTemplate>

Вопрос

Есть ли способ лучше (т.е. без прокси)?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
2 592
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Причина этого в том, что селектор шаблонов по умолчанию поддерживает только конкретные типы, но не интерфейсы. Вам необходимо создать собственный DataTemplateSelector и применить его к свойству ItemTemplateSelector TreeView. Я не могу найти URL-адрес, по которому я нашел его пример, но, надеюсь, с этой информацией вы сможете его погуглить.

Вы имеете в виду msdn.microsoft.com/en-us/library/…? Это, наверное, хорошая идея!

David Schmitt 16.12.2008 21:39

@ Ричард: Это не обязательно должен быть тип бетона. Даже абстрактные типы работают нормально. У меня была аналогичная проблема, и я заменил интерфейс IThing на абстрактный класс AbstractThing.

chikak 12.12.2010 17:06

Другое решение - вы даете ключ HierarchicalDataTemplate и помещаете его в Windows.Resources и вручную ссылаетесь на него в TreeView. <TreeView ItemDataTemplate = {StaticResource templateKey}/>

Но это ограничивает автоматический выбор шаблона данных в соответствии с типом данных, который предоставляется WPF TreeView.

Другая альтернатива (похожая на решение jing): если у вас есть только один тип элемента, вы можете установить ItemTemplate напрямую. Тогда вам не нужно устанавливать ключ или тип данных.

В вашей ViewModel:

public ObservableCollection<IThing> Thingies { get; private set; }

В представлении:

<TreeView ItemsSource = "{Binding Thingies}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource = "{Binding SomeThings}">
            <TextBox Text = "{Binding SomeString}" />    
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Другие вопросы по теме