Por que cabeçalhos de guia exibido na área de conteúdo de separadores em uma XAML TabControl?
-
22-07-2019 - |
Pergunta
Eu tenho um TabControl , cujo ItemsSource está ligado a uma coleção observável de pontos de vista ??strong> (UserControls) cada qual tem como seu elemento raiz TabItem . No entanto, quando ele é exibido, o Header o texto está no conteúdo de cada TabItem, como se UserControl invólucro está causando conflitos:
O TabControl está em 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>
O que eu tenho que mudar para que TabItems são exibidos como TabItems dentro do TabControl?
Aqui estão os pontos de vista TabItem chamado 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>
E aqui é onde eu criar e carregar cada vista para o 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);
}
Solução
Para qualquer ItemsControl, se os itens adicionados à sua colecção de itens (quer directamente ou através de ItemsSource) não são exemplo de recipiente de produto que de controlo, em seguida, cada produto é enrolado em um exemplo do recipiente de produto. O recipiente de produto é uma classe, tais como TabItem ou ListBoxItem. O contêiner de item normalmente é um ContentControl ou HeaderedContentControl, e seu item real é atribuído a sua propriedade de conteúdo, de modo que você pode usar modelos etc para controlar como o conteúdo é apresentado. Você também pode estilo do próprio contêiner de item usando a propriedade ItemContainerStyle do ItemControl.
Neste caso particular, você deve ligar ItemsSource a uma lista de SmartFormAreaPresenters. Em seguida, use algo como isto para o controle guia:
<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>
onde HeaderText é um imóvel adequado em seu SmartFormAreaPresenter. Você também deve remover o TabItem de sua definição SmartFormAreaView. O DataContext de cada exibição será automaticamente definido para o Presenter apropriada.
Veja do Dr. WPF blogue para uma excelente discussão de vários temas relacionados ItemsControl.
Outras dicas
O TabControl
aceitará seus controles como seus controles somente se pode ser convertido para TabItem
, não UserControl, ou SmartFormAreaView, etc.
Assim que você quer preencher TabItems
regular com sua árvore visual, ou você subclasse TabItems
, ou você subclasse o TabControl
para substituir sua IsItemItsOwnContainerOverride
método, a aceitar o seu tipo do recipiente.
O método deve ter a seguinte aparência:
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is YourControlTypeHere || item is TabItem;
}