Perché le intestazioni delle schede sono visualizzate nell'area del contenuto delle schede in un XCL TabControl?
-
22-07-2019 - |
Domanda
Ho un TabControl il cui ItemsSource è associato a una raccolta osservabile di visualizzazioni (UserControls) ciascuno che ha come elemento radice un TabItem . Tuttavia, quando viene visualizzato, il testo Intestazione è nel contenuto di ciascun TabItem, come se il wrapper UserControl causasse conflitti:
TabControl è in 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>
Cosa devo modificare in modo che TabItems venga visualizzato come TabItems all'interno di TabControl?
Ecco le visualizzazioni TabItem chiamate 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>
Ed ecco dove creo e carico ogni vista in 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);
}
Soluzione
Per qualsiasi ItemsControl, se gli articoli aggiunti alla sua raccolta Items (direttamente o tramite ItemsSource) non sono istanza del contenitore degli articoli di quel controllo, ogni articolo viene avvolto in un'istanza del contenitore degli articoli. Il contenitore di elementi è una classe come TabItem o ListBoxItem. Il contenitore degli articoli è normalmente ContentControl o HeaderedContentControl e il tuo oggetto reale è assegnato alla sua proprietà Content, quindi puoi usare modelli ecc. Per controllare come viene presentato il contenuto. Puoi anche assegnare uno stile al contenitore articoli stesso usando la proprietà ItemContainerStyle di ItemControl.
In questo caso particolare, è necessario associare ItemsSource a un elenco di SmartFormAreaPresenters. Quindi utilizzare qualcosa del genere per il controllo scheda:
<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>
dove HeaderText è una proprietà adatta su SmartFormAreaPresenter. È inoltre necessario rimuovere TabItem dalla definizione di SmartFormAreaView. Il DataContext di ciascuna vista verrà automaticamente impostato sul Presenter appropriato.
Vedi il blog del Dr. WPF per una discussione eccellente di vari argomenti relativi a ItemsControl.
Altri suggerimenti
Il TabControl
accetterà i tuoi controlli come controlli solo se possono essere lanciati su TabItem
, non UserControl o SmartFormAreaView, ecc.
Quindi riempi il TabItems
normale con la tua struttura visiva, o esegui la sottoclasse TabItems
, o subclassi il TabControl
per sovrascriverlo IsItemItsOwnContainerOverride
metodo, per accettare il tipo come contenitore.
Il metodo dovrebbe apparire come segue:
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is YourControlTypeHere || item is TabItem;
}