plantillas - WPF HiercharchicalDataTemplate.DataType: ¿Cómo reaccionar en las interfaces?
wpf templates free (3)
Problema
Tengo una colección de IThing
s y me gustaría crear una HierarchicalDataTemplate
para TreeView
. El sencillo DataType={x:Type local:IThing}
por supuesto no funciona, probablemente porque los creadores de WPF no querían manejar las posibles ambigüedades.
Como esto debería manejar IThing
s de diferentes fuentes al mismo tiempo, hacer referencia a la clase de implementación está fuera de toda duda.
Solución actual
Por ahora estoy usando un ViewModel que proxies IThing a través de una implementación concreta:
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>
Pregunta
¿Hay alguna forma mejor (es decir, sin proxy)?
La razón de esto es que el selector de plantilla predeterminado solo admite tipos concretos, no interfaces. Debe crear un DataTemplateSelector personalizado y aplicarlo a la propiedad ItemTemplateSelector de TreeView. No puedo encontrar la URL donde encontré un ejemplo, pero espero que con esta información, pueda buscarla en Google.
Otra solución es dar una clave a HierarchicalDataTemplate y ponerla en Windows.Resources, y hacer referencia a ella manualmente en TreeView. <TreeView ItemDataTemplate={StaticResource templateKey}/>
Pero eso limita la autoselección de la plantilla de datos según el tipo de datos, que proporciona WPF TreeView.
Otra alternativa (similar a la solución de jing): si solo tiene un tipo de artículo, puede establecer ItemTemplate directamente. Entonces no necesita establecer una clave o un tipo de datos.
En su ViewModel:
public ObservableCollection<IThing> Thingies { get; private set; }
En la vista:
<TreeView ItemsSource="{Binding Thingies}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SomeThings}">
<TextBox Text="{Binding SomeString}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>