wpf - 如何从 ContentTemplate 绑定(bind)到周围的自定义控件?

标签 wpf xaml binding datatemplate

我有以下用户控制:

<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' 来实现一个接口(interface)。我想从 TabItem 中绑定(bind)到这个属性和其他属性。的DataTemplate .但是由于奇怪的交互,TextBlockDataTemplate 内绑定(bind)到 父容器 TabItem ,也称为“Self”,但在另一个 Xaml 文件中定义。

问题

为什么绑定(bind)在 TabItem.Header 中起作用,但在 TabItem.ContentTemplate 中不起作用,我应该如何继续从 DataTemplate 中获取用户控件的属性?

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

  • 我想我可以替换整个 ControlTemplate达到我正在寻找的效果,但由于我想保留 TabItem 的默认外观和感觉无需维护整个ControlTemplate ,我很不愿意这样做。

    编辑

    同时我发现问题是:TabControl s 不能有(任何)ItemsTemplate (包括 DisplayMemberPath )如果 ItemsSource包含 Visual s。有a thread on MSDN Forum explaining why .

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

    最佳答案

    问题似乎是您使用的是 ContentTemplate 而没有实际使用 content 属性。 ContentTemplate 的DataTemplate 的默认DataContext 是TabItem 的Content 属性。然而,我所说的都没有真正解释为什么绑定(bind)不起作用。不幸的是,我不能给你一个明确的答案,但我最好的猜测是,这是因为 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>
    

    关于wpf - 如何从 ContentTemplate 绑定(bind)到周围的自定义控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/148704/

    相关文章:

    c# - 如何确保 ViewModel 属性在再次更改其值之前已绑定(bind)在 View 上?

    c# - 如何在 WPF 中添加自定义路由命令?

    c# - 在 XAML 中禁用动画?

    wpf - 获取 ProgressBar 来填充 StatusBarItem

    java - 使用导入的 XSD 和绑定(bind)生成 JAXB 类

    .net - 为什么 .Net WPF DependencyProperties 必须是类的静态成员

    c# - 在CodeBehind中获取ListViewItem控件

    binding - Prolog中变量的几种绑定(bind)选项

    C# - 将 View 作为参数传递给转换器

    c# - 使用 GridSplitter 调整网格大小