¿Por qué se muestran los encabezados de las pestañas en el área de contenido de las pestañas en un XAML TabControl?

StackOverflow https://stackoverflow.com/questions/1226622

Pregunta

Tengo un TabControl cuyo ItemsSource está vinculado a una colección de vistas observables (UserControls), cada una de las cuales tiene como elemento raíz un TabItem . Sin embargo, cuando se muestra, el texto Encabezado está en el contenido de cada TabItem, como si el contenedor UserControl causara conflictos:

 texto alternativo

El TabControl está en SmartFormView.xaml:

<UserControl x:Class="TestApp.Views.SmartFormView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel
        Margin="10">
        <TextBlock Text="{Binding Title}"
            FontSize="18"/>
        <TextBlock Text="{Binding Description}"
            FontSize="12"/>

        <TabControl
            Margin="0 10 0 0"
            ItemsSource="{Binding SmartFormAreaViews}"/>
    </StackPanel>
</UserControl>

¿Qué debo cambiar para que los TabItems se muestren como TabItems dentro del TabControl?

Aquí están las vistas de TabItem llamadas SmartFormAreaView.xaml:

<UserControl x:Class="TestApp.Views.SmartFormAreaView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TabItem Header="This is the header">
        <StackPanel Margin="10">
            <TextBlock Text="this is the content"/>
        </StackPanel>
    </TabItem>
</UserControl>

Y aquí es donde creo y cargo cada vista en ObservableCollection :

var areas = from area in xmlDoc.Descendants("area")
            select area;
foreach (var area in areas)
{
    SmartFormArea smartFormArea = new SmartFormArea();
    smartFormArea.IdCode = area.Attribute("idCode").Value;
    smartFormArea.Title = area.Attribute("title").Value;
    SmartFormAreaPresenter smartFormAreaPresenter = new SmartFormAreaPresenter(smartFormArea);
    SmartFormAreaViews.Add(smartFormAreaPresenter.View as SmartFormAreaView);
}
¿Fue útil?

Solución

Para cualquier control de elementos, si los elementos agregados a su colección de elementos (ya sea directamente o mediante ItemsSource) no son una instancia del contenedor de elementos de ese control, entonces cada elemento se envuelve en una instancia del contenedor de elementos. El contenedor de elementos es una clase como TabItem o ListBoxItem. El contenedor del elemento normalmente es un ContentControl o HeaderedContentControl, y su elemento real se asigna a su propiedad Content, por lo que puede usar plantillas, etc. para controlar cómo se presenta el contenido. También puede diseñar el contenedor del elemento en sí utilizando la propiedad ItemContainerStyle de ItemControl.

En este caso particular, debe vincular ItemsSource a una lista de SmartFormAreaPresenters. Luego use algo como esto para el control de pestañas:

<TabControl ItemsSource="{Binding SmartFormAreaPresenters}">
  <TabControl.ItemContainerStyle>
    <Style TargetType="{x:Type TabItem}">
      <Setter Property="Header" Value="{Binding HeaderText}" />
    </Style>
  </TabControl.ItemContainerStyle>

  <TabControl.ContentTemplate>
    <DataTemplate DataType="{x:Type local:SmartFormAreaPresenter}">
      <local:SmartFormAreaView />
    </DataTemplate>
  </TabControl.ContentTemplate>
</TabControl>

donde HeaderText es una propiedad adecuada en su SmartFormAreaPresenter. También debe eliminar el TabItem de su definición SmartFormAreaView. El DataContext de cada Vista se establecerá automáticamente en el Presentador apropiado.

Vea el blog del Dr. WPF para una excelente discusión de varios temas relacionados con ItemsControl.

Otros consejos

El TabControl aceptará sus controles como sus controles solo si se pueden convertir a TabItem , no a UserControl, o SmartFormAreaView, etc.

Entonces, o bien llena TabItems con su árbol visual, o subclasifica TabItems , o subclasifica el TabControl para anular su IsItemItsOwnContainerOverride método, para aceptar su tipo como contenedor.

El método debería tener el siguiente aspecto:

protected override bool IsItemItsOwnContainerOverride(object item)
{
    return item is YourControlTypeHere || item is TabItem;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top