8 Stimmen

Wie bindet man ein ContentTemplate an das umgebende Custom Control?

Ich habe die folgende Benutzerkontrolle:

<TabItem 
    x:Name="Self"
    x:Class="App.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:App"
    >
    <TabItem.Header>
        <!-- This works -->
        <TextBlock Text="{Binding ElementName=Self, Path=ShortLabel, UpdateSourceTrigger=PropertyChanged}"/>
    </TabItem.Header>
    <TabItem.ContentTemplate>
        <DataTemplate>
            <!-- This binds to "Self" in the surrounding window's namespace -->
            <TextBlock Text="{Binding ElementName=Self, Path=ShortLabel, UpdateSourceTrigger=PropertyChanged}"/>

Dieses benutzerdefinierte TabItem definiert eine DependencyProperty ShortLabel', um eine Schnittstelle zu implementieren. Ich möchte an diese und andere Eigenschaften aus der TabItem 's DataTemplate . Doch aufgrund merkwürdiger Wechselwirkungen ist die TextBlock innerhalb der DataTemplate wird an den übergeordneter Container der TabItem die ebenfalls "Self" heißt, aber in einer anderen Xaml-Datei definiert ist.

Frage

Warum funktioniert die Bindung in der TabItem.Header, aber nicht aus TabItem.ContentTemplate, und wie sollte ich vorgehen, um die Eigenschaften des Benutzersteuerelements aus dem DataTemplate zu erhalten?

Was ich bereits ausprobiert habe

  • TemplateBinding : Versucht, sich mit dem ContentPresenter innerhalb der Eingeweide des TabItem .
  • FindAncestor, AncestorType={x:Type TabItem} : Findet nicht die TabItem Elternteil. Dies funktioniert auch nicht, wenn ich die MyTabItem Typ.
  • ElementName=Self : Versucht, an ein Steuerelement mit diesem Namen im falschen Bereich zu binden (übergeordneter Container, nicht TabItem ). Ich denke, das gibt einen Hinweis darauf, warum es nicht funktioniert: Das DataTemplate wird nicht an dem Punkt erstellt, an dem es in XAML definiert wird, sondern offenbar vom übergeordneten Container.

Ich nehme an, ich könnte die gesamte ControlTemplate um den gewünschten Effekt zu erzielen, aber da ich das Standard-Look-and-Feel der Website beibehalten möchte TabItem ohne das gesamte System pflegen zu müssen ControlTemplate Ich zögere sehr, dies zu tun.

編集

Inzwischen habe ich herausgefunden, dass es sich um ein Problem handelt: TabControl s kann nicht (keine) ItemsTemplate (das schließt die DisplayMemberPath ), wenn die ItemsSource enthält Visual s. Dort ein Thread im MSDN-Forum, der erklärt, warum .

Da dies ein grundlegendes Problem mit WPFs TabControl zu sein scheint, schließe ich die Frage. Vielen Dank für alle Ihre Hilfe!

2voto

Todd White Punkte 7772

Das Problem scheint darin zu bestehen, dass Sie ein ContentTemplate verwenden, ohne die Eigenschaft content tatsächlich zu nutzen. Der Standard DataContext für das ContentTemplate DataTemplate ist die Eigenschaft Content von TabItem. Allerdings erklärt nichts von dem, was ich sagte tatsächlich warum die Bindung funktioniert nicht. Leider kann ich Ihnen keine endgültige Antwort geben, aber meine beste Vermutung ist, dass es auf die Tatsache zurückzuführen ist, dass das TabControl einen ContentPresenter wiederverwendet, um die Inhaltseigenschaft für alle Registerkartenelemente anzuzeigen.

In Ihrem Fall würde ich also den Code so ändern, dass er etwa so aussieht:

<TabItem
    x:Class="App.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:App"
    Header="{Binding ShortLabel, RelativeSource={RelativeSource Self}}"
    Content="{Binding ShortLabel, RelativeSource={RelativeSource Self}}" />

Wenn ShortLabel ein komplexeres Objekt und nicht nur eine Zeichenkette ist, sollten Sie ein ContentTemplate einführen:

<TabItem
    x:Class="App.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:App"
    Header="{Binding ShortLabel, RelativeSource={RelativeSource Self}}"
    Content="{Binding ComplexShortLabel, RelativeSource={RelativeSource Self}}">
    <TabItem.ContentTemplate>
        <DataTemplate TargetType="{x:Type ComplexType}">
            <TextBlock Text="{Binding Property}" />
        </DataTemplate>
    </TabItem.ContentTemplate>
</TabItem>

1voto

Bob King Punkte 24518

Versuchen Sie dies. Ich bin nicht sicher, ob es funktioniert oder nicht, aber

<TabItem 
    x:Name="Self"
    x:Class="App.MyTabItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:App"
    >
    <TabItem.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=ShortLabel}"/>
        </DataTemplate>
    </TabItem.ContentTemplate>
</TabItem>

Wenn das nicht funktioniert, versuchen Sie, dieses Attribut in den <TabItem/> einzufügen:

DataContext="{Binding RelativeSource={RelativeSource self}}"

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X