У меня есть коллекция 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>
Есть ли способ лучше (т.е. без прокси)?





Причина этого в том, что селектор шаблонов по умолчанию поддерживает только конкретные типы, но не интерфейсы. Вам необходимо создать собственный DataTemplateSelector и применить его к свойству ItemTemplateSelector TreeView. Я не могу найти URL-адрес, по которому я нашел его пример, но, надеюсь, с этой информацией вы сможете его погуглить.
@ Ричард: Это не обязательно должен быть тип бетона. Даже абстрактные типы работают нормально. У меня была аналогичная проблема, и я заменил интерфейс IThing на абстрактный класс AbstractThing.
Другое решение - вы даете ключ 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>
Вы имеете в виду msdn.microsoft.com/en-us/library/…? Это, наверное, хорошая идея!