2010-09-20 3 views
3

Je crois que c'est un bug dans WPF (v4.0 si c'est important), mais il est tard, et peut-être qu'il me manque quelque chose.WTF WPF TabControl?

Je suis liaison à un faux exemple à des fins d'illustration:

<x:Array x:Key="SampleItems" Type="sys:String"> 
     <sys:String>Foo</sys:String> 
     <sys:String>Bar</sys:String> 
     <sys:String>Baz</sys:String> 
    </x:Array> 

Cela fonctionne et affiche trois onglets avec le même en-tête et le contenu:

<TabControl ItemsSource="{StaticResource SampleItems}"> 
      <TabControl.ItemContainerStyle> 
       <Style TargetType="TabItem"> 
        <Setter Property="Header" Value="{Binding}" /> 
        <Setter Property="Content" Value="{Binding}" /> 
       </Style> 
      </TabControl.ItemContainerStyle> 
     </TabControl> 

Cependant, cela jette une exception à la message "Erreur 10 L'élément spécifié est déjà l'enfant logique d'un autre élément Déconnectez-le en premier.":

<TabControl ItemsSource="{StaticResource SampleItems}"> 
    <TabControl.ItemContainerStyle> 
     <Style TargetType="TabItem"> 
      <Setter Property="Header"> 
       <Setter.Value> 
        <!-- Anything here causes this problem. --> 
        <TextBlock Text="{Binding}"/> 
       </Setter.Value> 
      </Setter> 
      <Setter Property="Content" Value="{Binding}" /> 
     </Style> 
    </TabControl.ItemContainerStyle> 
</TabControl> 

Il est important de noter que ceci est reproductible avec n'importe quel texte de TextBlock. En fait, je peux remplacer l'entête TextBlock par n'importe quel XAML et recevoir ce message. Je ne peux pas expliquer cela. Des idées, ou est-ce juste un bug?

Le problème apparaît dans le concepteur VS, mais voici une partie de la trace de la pile correspondant à l'exécution ainsi:

at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent) 
    at System.Windows.FrameworkElement.AddLogicalChild(Object child) 
    at System.Windows.Controls.HeaderedContentControl.OnHeaderChanged(Object oldHeader, Object newHeader) 
    at System.Windows.Controls.HeaderedContentControl.OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) 
    at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
    at System.Windows.StyleHelper.ApplyStyleOrTemplateValue(FrameworkObject fo, DependencyProperty dp) 
    at System.Windows.StyleHelper.InvalidateContainerDependents(DependencyObject container, FrugalStructList`1& exclusionContainerDependents, FrugalStructList`1& oldContainerDependents, FrugalStructList`1& newContainerDependents) 
    at System.Windows.StyleHelper.DoStyleInvalidations(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle) 
    at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache) 
    at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) 
    at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
    at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) 
    at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) 
    at System.Windows.Controls.ItemsControl.ApplyItemContainerStyle(DependencyObject container, Object item) 
    at System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.PrepareItemContainer(DependencyObject container, Object item) 
    at System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IItemContainerGenerator.PrepareItemContainer(DependencyObject container) 
    at System.Windows.Controls.Panel.GenerateChildren() 

Répondre

5

Fondamentalement, ce que vous faites est d'attribuer la même instance d'un TextBlock à chaque TabItem. À la première itération, le TextBlock est ajouté au premier TabItem. Lors de la deuxième itération, le même identique TextBlock est ajouté à l'arborescence visuelle. Le message d'erreur que vous voyez est en train de vous dire que le TextBlock ne peut pas avoir deux parents (il y a une blague quelque part).

Vous pouvez définir un modèle pour ceux-ci, cependant. Un modèle indique à TabItem de créer un nouvel ensemble de tous les éléments visuels souhaités par élément créé.

<TabControl ItemsSource="{StaticResource SampleItems}"> 
    <TabControl.ItemContainerStyle> 
     <Style TargetType="TabItem"> 
      <Setter Property="HeaderTemplate"> 
       <Setter.Value> 
        <DataTemplate> 
         <TextBlock Text="{Binding}"/> 
        </DataTemplate> 
       </Setter.Value> 
      </Setter> 
      <Setter Property="Content" Value="{Binding}" /> 
     </Style> 
    </TabControl.ItemContainerStyle> 
</TabControl> 
+0

Bien sûr. Même si le XAML net était approximativement le même, où dans le cas de travail un TextBlock était inséré pour chaque chaîne liée, la différence clé est qu'un nouveau TextBlock était généré pour chaque chaîne. Dans le cas de l'échec, je lui disais d'utiliser le même encore et encore. Honte sur moi. –

Questions connexes