2009-08-04 7 views
3

J'ai un TabControl dont ItemsSource est lié à une collection observable de vues (UserControls) qui ont chacun comme élément racine d'un TabItem. Cependant, lorsqu'il est affiché, l'en-tête texte est dans le contenu de chaque TabItem, comme si UserControl wrapper est à l'origine des conflits:Pourquoi les en-têtes d'onglet sont-ils affichés dans la zone de contenu des onglets d'un TabControl XAML?

alt text http://i31.tinypic.com/2z7pctz.png

TabControl est 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> 

Que dois-je changer pour que les TabItems soient affichés sous forme de TabItems dans le TabControl?

Voici les vues TabItem appelé 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> 

Et voici où je crée et charge de chaque vue dans le 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); 
} 

Répondre

4

Pour toute ItemsControl, si les éléments ajoutés à sa collection Items (soit directement, soit par l'intermédiaire ItemsSource) ne sont pas par exemple du conteneur d'éléments de ce contrôle, chaque élément est enveloppé dans une instance du conteneur d'éléments. Le conteneur d'élément est une classe telle que TabItem ou ListBoxItem. Le conteneur d'éléments est normalement un ContentControl ou un HeaderedContentControl, et votre élément actuel est assigné à sa propriété Content, vous pouvez donc utiliser des templates, etc. pour contrôler la façon dont le contenu est présenté. Vous pouvez également styler le conteneur d'élément lui-même à l'aide de la propriété ItemContainerStyle de ItemControl.

Dans ce cas particulier, vous devez lier ItemsSource à une liste de SmartFormAreaPresenters. Ensuite, utilisez quelque chose comme ça pour le contrôle onglet:

<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> 

où HeaderText est une propriété appropriée sur votre SmartFormAreaPresenter. Vous devez également supprimer le TabItem de votre définition SmartFormAreaView. Le DataContext de chaque vue sera automatiquement défini sur le présentateur approprié.

Voir le document blog de Dr. WPF pour une excellente discussion sur divers sujets liés à ItemsControl.

0

Le TabControl sera n'acceptez vos contrôles comme contrôles que s'ils peuvent être transtypés en TabItem, pas en UserControl ou SmartFormAreaView, etc.

Donc soit vous remplissez TabItems régulier avec votre arbre visuel, ou vous sous-classe TabItems, ou vous le sous-classe TabControl pour remplacer sa méthode IsItemItsOwnContainerOverride, d'accepter votre type que le conteneur.

La méthode devrait se présenter comme suit:

protected override bool IsItemItsOwnContainerOverride(object item) 
{ 
    return item is YourControlTypeHere || item is TabItem; 
}