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

8

我有以下用户控件:

<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,所以我非常不愿意这样做。

编辑

同时,我已经发现问题所在:如果TabControl包含Visual,那么它就不能有(任何)ItemsTemplate(这包括DisplayMemberPath)。这里有一篇MSDN论坛上的帖子解释为什么
由于这似乎是WPF的TabControl的一个根本性问题,我将关闭这个问题。感谢你们所有人的帮助!

David Schmitt - 也许你可以将你找到的信息发布为答案并接受它?因为关闭问题没有任何意义,而有了答案就可以帮助别人了。 - MikroDel
@MikroDel:我没有意图通过这个答案获得声望。你可以自由地将我在问题下“编辑”所写的内容作为答案发布和完善。这并不改变WPF不支持这个特定用例的事实。 - David Schmitt
这不是关于回答的声望。答案也可以是否定的 - 例如在这里“WPF不支持...”。我的意思是,如果将其放置为答案而不是问题,其他用户将更容易找到信息。 - MikroDel
你可以将其发布为答案并接受它。我不想这样做(发布为答案),因为我还没有找到这个信息。 - MikroDel
2个回答

2
看起来问题是您正在使用ContentTemplate,但实际上没有使用content属性。 ContentTemplate的DataTemplate的默认DataContext是TabItem的Content属性。然而,我说的这些都不解释为什么绑定不起作用。不幸的是,我无法给出明确的答案,但我最好的猜测是由于TabControl重用ContentPresenter来显示所有选项卡项的内容属性。
因此,在您的情况下,我建议将代码更改为以下内容:
<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>

1
试一下。我不确定是否有效,但是
<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>

如果不起作用,请尝试将此属性添加到中:
DataContext="{Binding RelativeSource={RelativeSource self}}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接