У меня есть следующий пользовательский элемент управления:
<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' для реализации интерфейса. Я хотел бы выполнить привязку к этому и другим свойствам из TabItemDataTemplate. Но из-за странных взаимодействий 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 не может иметь (любого) ItemsTemplate (включая DisplayMemberPath), если ItemsSource содержит Visual. Есть ветка на форуме MSDN, объясняющая, почему.
Поскольку это кажется фундаментальной проблемой с WPF TabControl, я закрываю вопрос. Спасибо за вашу помощь!
@MikroDel: Я не собираюсь отбирать репутацию за этот ответ. Вы можете публиковать и улучшать то, что я написал в разделе «Редактировать» в вопросе в качестве ответа. Это не меняет того факта, что WPF не поддерживает этот конкретный вариант использования.
Дело не в репутации для ответа. Ответ также может быть отрицательным - например, здесь «WPF не поддерживает ...». Я имею в виду, что другим пользователям будет легче найти информацию, если она будет размещена в качестве ответа, а не в вопросе.
Вы можете опубликовать его как ответ и принять его. Я не хочу этого делать (опубликуйте ответ), потому что не нашел этой информации.





Попробуй это. Не уверен, сработает это или нет, но
<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. 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>
Дэвид Шмитт - может быть, лучше опубликовать найденную информацию в качестве ответа и принять ее? Потому что нет причин закрывать вопрос, а с ответом он может быть полезен.