Как привязать ContentTemplate к окружающему пользовательскому элементу управления? - PullRequest
6 голосов
/ 29 сентября 2008

У меня есть следующий пользовательский элемент управления:

<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. Но из-за странных взаимодействий TextBlock в DataTemplate связывается с родительским контейнером TabItem, который также называется «Self», но определен в другом файле Xaml.

Вопрос

Почему привязка работает в TabItem.Header, но не из TabItem.ContentTemplate, и как мне перейти к свойствам пользовательского элемента управления из DataTemplate?

Что я уже пробовал

  • TemplateBinding: Пытается привязаться к ContentPresenter в пределах TabItem.
  • FindAncestor, AncestorType={x:Type TabItem}: Не находит TabItem родитель. Это также не работает, когда я указываю тип MyTabItem.
  • ElementName=Self: Пытается привязать элемент управления с таким именем в неверной области (родительский контейнер, а не TabItem). Я думаю, что это дает подсказку, почему это не работает: DataTemplate создается не в том месте, где он определен в XAML, а, по-видимому, в родительском контейнере.

Полагаю, я мог бы заменить целое ControlTemplate для достижения нужного эффекта, но, поскольку я хочу сохранить внешний вид и восприятие по умолчанию TabItem без необходимости сохранять целое ControlTemplate, я Я очень не хочу этого делать.

Редактировать

Тем временем я обнаружил, что проблема в том, что TabControl s не может иметь (любой) ItemsTemplate (включая DisplayMemberPath), если ItemsSource содержит Visual s. На форуме MSDN есть ветка , объясняющая, почему .

Поскольку это похоже на фундаментальную проблему с TabFontrol в WPF, я закрываю вопрос. Спасибо за вашу помощь!

Ответы [ 2 ]

1 голос
/ 01 ноября 2008

Проблема, по-видимому, заключается в том, что вы используете ContentTemplate без фактического использования свойства content. DataContext по умолчанию для DataTemplate ContentTemplate является свойством Content объекта TabItem. Однако ничего из того, что я сказал, на самом деле не объясняет , почему привязка не работает. К сожалению, я не могу дать вам однозначный ответ, но, скорее всего, это связано с тем, что 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 голос
/ 08 октября 2008

Попробуй это. Я не уверен, будет ли это работать или нет, но

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