如何从ContentTemplate绑定到周围的自定义控件?

时间:2020-03-06 14:52:27  来源:igfitidea点击:

我有以下用户控件:

<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}"/>

这个自定义的TabItem定义了一个DependencyProperty'ShortLabel'来实现一个接口。我想从" TabItem"的" DataTemplate"内部绑定到此属性和其他属性。但是由于奇怪的交互作用,DataTemplate中的TextBlock被绑定到TabItem的父容器,该容器也称为" Self",但在另一个Xaml文件中定义。

问题

为什么绑定在TabItem.Header中起作用,但不能在TabItem.ContentTemplate内部起作用,又该如何从DataTemplate内部获得用户控件的属性?

我已经尝试过的

  • TemplateBinding:试图绑定到TabItem内胆中的ContentPresenter。
  • FindAncestor,AncestorType = {x:Type TabItem}:找不到TabItem父对象。当我指定MyTabItem类型时,这也不起作用。
  • ElementName = Self:试图绑定到具有错误范围内的该名称的控件(父容器,而不是TabItem)。我认为这提示了为什么它不起作用:DataTemplate不是在XAML中定义的位置创建的,而是显然由父容器创建的。

我想我可以替换整个ControlTemplate来达到我想要的效果,但是由于我想保留TabItem的默认外观而不必维护整个ControlTemplate,所以我非常不愿意这样做。

编辑

同时,我发现问题在于:如果ItemsSource包含Visual,那么TabControl不能具有(任何)ItemsTemplate(包括DisplayMemberPath)。 MSDN论坛上有一个线程解释原因。

由于这似乎是WPF的TabControl的基本问题,因此我要结束这个问题。感谢你的帮助!

解决方案

试试这个。我不确定是否可以使用,但是

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

如果不起作用,请尝试将此属性粘贴在<TabItem />中:

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

问题似乎在于我们在使用ContentTemplate而不实际使用content属性。 ContentTemplate的DataTemplate的默认DataContext是TabItem的Content属性。但是,我所说的都没有真正解释为什么绑定不起作用。不幸的是,我无法给出确切的答案,但我最大的猜测是,由于TabControl重用ContentPresenter来显示所有选项卡项目的content属性。

因此,在情况下,我将代码更改为如下所示:

<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}}" />

如果ShortLabel是一个更复杂的对象,而不仅仅是一个字符串,那么我们将要引入一个ContentTemplate:

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