2010-09-20 124 views
3

我相信這是WPF中的一個bug(如果它很重要,那麼v4.0),但是已經很晚了,也許我錯過了一些東西。WTF WPF TabControl?

我結合用於說明目的假例如:

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

這工作,並顯示三個選項卡具有相同的標題和內容:

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

但是,這將引發與異常消息「錯誤10指定的元素已經是另一個元素的邏輯子元素,請先斷開連接」:

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

重要的是要注意,這可以在TextBlock中的任何文本中重現。實際上,我可以用任何XAML替換標題TextBlock並獲取此消息。我無法解釋這一點。任何想法,或者這只是一個錯誤?

的問題出現在VS設計師,但這裏是在運行時,相關的堆棧跟蹤的一部分,以及:

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

回答

5

基本上你正在做的是分配TextBlock的非常相同的情況下,以每TabItem的。在第一次迭代中,TextBlock被添加到第一個TabItem中。在第二次迭代時,將非常一致的 TextBlock添加到可視化樹中。你看到的錯誤信息是試圖告訴你TextBlock不能有兩個父母(那裏有個玩笑)。但是,您可以爲設置一個模板。模板指示TabItem爲每個項目創建的任何視覺創建一組新的視圖。

<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

當然。即使網絡XAML大致相同,在工作案例中爲每個綁定字符串插入TextBlock的位置,關鍵區別在於爲每個字符串生成了一個新的TextBlock。在失敗的案例中,我告訴它反覆使用同一個案例。對我感到羞恥。 – 2010-09-20 17:28:25