WPF: TabControl & DataTemplates
(1)
Solo quiero entender el siguiente escenario. Donde estoy implementando un <TabControl>
enlazado a un ObservableCollection<TabViewModel>
No hay plantillas de datos
Cuando no tengo ningún DataTemplate
, aparece el texto WpfApplication1.TabViewModel
en el encabezado y el contenido de la pestaña. Ok, entiendo esta parte.
Just ItemTemplate
Cuando solo tengo
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding TabTitle}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
Entonces mi encabezado de pestañas se llena. El contenido de la pestaña sigue siendo WpfApplication1.TabViewModel
.
Solo DataTemplate
Cuando acabo de tener lo siguiente en mi <Window.Resources>
<DataTemplate DataType="{x:Type local:TabViewModel}">
<TextBox Text="{Binding Text}" />
</DataTemplate>
Estas plantillas llenan el encabezado de la pestaña.
Ambos
Cuando tengo ambas, ItemTemplate
completa el encabezado de la pestaña mientras DataTemplate
llena el contenido de la pestaña. Por qué toda esta diferencia ItemTemplate
y DataTemplate
llena el encabezado de la pestaña si el otro no está presente. Si ambos están presentes, ItemTemplate
llena el encabezado mientras DataTemplate
llena el contenido.
Aunque tengo cosas que funcionan, estoy bastante confundido. ¿No debería algo como <TabControl.HeaderTemplate>
ser lo que llena el encabezado y <TabControl.ItemTemplate>
llenar el contenido?
En primer lugar, hay dos plantillas involucradas aquí:
-
TabControl.ItemTemplate
, utilizado para representar los encabezadosTabItem
-
TabControl.ContentTemplate
, utilizado para representar el contenido deTabItem
Si no establece estas propiedades explícitamente, WPF intentará resolverlas en otro lugar. Recorrerá el árbol lógico en busca de un recurso que le indique cómo representar su modelo de vista. Si encuentra un DataTemplate
que tiene un DataType
coincidente pero no tiene una clave, lo usará para representar el modelo de vista. Si no encuentra uno, se ToString
forma predeterminada para representar el valor de ToString
del objeto.
Entonces, si quieres ser explícito, quieres algo como esto:
<TabControl ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabTitle}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Como no es específico, WPF está intentando avanzar por su árbol lógico para encontrar un DataTemplate
apropiado. Cuando lo encuentra, lo usa para renderizar el modelo de vista. Donde no lo encuentra, llama a ToString
y lo renderiza.
Así que para abordar sus casos específicos:
Just ItemTemplate
Ha indicado explícitamente cómo representar los encabezados de las pestañas, pero no su contenido. Por lo tanto, el primero se procesa utilizando la DataTemplate
proporcionada, pero el último se establecerá de forma predeterminada en ToString
.
Solo DataTemplate
No ha indicado explícitamente cómo representar los encabezados de las pestañas o su contenido. Por lo tanto, WPF busca una DataTemplate
adecuada para ambos. Como ambos contienen una instancia de su modelo de vista (ese es su DataContext
), entonces se usará el mismo DataTemplate
para representar encabezados de pestañas y sus contenidos.
NOTA: no declaró explícitamente que esto es lo que está sucediendo en su pregunta. Corrígeme si estoy equivocado.
Ambos
En este caso, ha indicado explícitamente cómo representar los encabezados de las pestañas, pero no los contenidos de las pestañas. Por lo tanto, el DataTemplate
explícito se usa para los encabezados de pestañas y el DataTemplate
implícito se usa para los contenidos de pestañas.