WTF WPF TabControl?
-
04-10-2019 - |
質問
これはWPF(重要な場合はv4.0)のバグだと思いますが、遅れており、何かが足りないと思います。
私は説明の目的のために偽の例に拘束しています:
<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>
これにより、同じヘッダーとコンテンツを含む3つのタブが機能し、表示されます。
<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に置き換えて、このメッセージを取得できます。私はこれを説明するために途方に暮れています。何かアイデア、またはこれは単なるバグですか?
問題は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()
解決
基本的に、あなたがしていることは、各Tabitemにテキストブロックのまったく同じインスタンスを割り当てることです。最初のイテレーションでは、テキストブロックが最初のTabitemに追加されます。 2番目の反復では、 まったく同じ TextBlockが視覚ツリーに追加されます。あなたが見るエラーメッセージは、TextBlockに2人の親がいないことを伝えようとしています(どこかに冗談があります)。
君 できる ただし、これらのテンプレートを設定します。テンプレートは、作成されたアイテムごとに必要な視覚的なものの新しいセットを作成するように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>
所属していません StackOverflow