Свойство DataContext FrameworkElement НЕ наследует дерево элементов
Здравствуйте, WPF Pros, по крайней мере, я надеюсь, что некоторые из вас читают это!
DataContext является свойством FrameworkElement (базовый класс для всех элементов управления WPF) и реализуется как DependencyProperty. Это означает, что все элементы-потомки в логическом дереве совместно используют один и тот же DataContext.
Таким образом, ContentControl должен делать это с его потомками, верно?
У меня есть сценарий, в котором это НЕ так, и я хотел бы знать, ЧТО является причиной такого плохого поведения?!
Что вы понимаете немного больше об этом, пожалуйста, прочитайте эту ветку (не хочу копировать все здесь), где проблема начинается...:
WPF: не удается найти цель триггера 'cc'. Цель должна появляться перед любыми сеттерами, триггерами
и сказать это короткими словами: у моих DataTemplates в ContentControl действительно есть мертвый DataContext, что означает, что НИЧЕГО не нужно связывать с ним, что на самом деле невозможно...
Каждый элемент в ContentControl НИЧЕГО не установлен в свойстве DataContext???
4 ответа
DataContext является свойством FrameworkElement (базовый класс для всех элементов управления WPF) и реализуется как DependencyProperty. Это означает, что все элементы-потомки в логическом дереве совместно используют один и тот же DataContext.
Тот факт, что это свойство зависимости не подразумевает наследование... Это верно для DataContext
, но только потому, что свойство зависимости имеет FrameworkPropertyMetadataOptions.Inherits
флаг в его метаданных.
Таким образом, ContentControl должен делать это с его потомками, верно?
ContentControl
немного особенным: DataContext
его потомков (визуальное дерево, построенное из DataTemplate
) на самом деле быть Content
из ContentControl
, Так что если ваш ContentControl
не имеет содержания, DataContext
внутри это ноль.
Это сработало для меня:
<ContentControl ContentTemplate="{StaticResource NotesTemplate}"
Content="{Binding}"
DataContext="{Binding HeightField}"/>
Без Content="{Binding}"
, DataContext был НЕДЕЙСТВИТЕЛЕН
Последний ответ (от VinceF) тоже сработал.
Я хотел показать usercontrol в зависимости от значения свойства в моей viewmodel. Поэтому я сделал ContentControl с некоторыми стилями триггеров. В зависимости от значения свойства привязки триггер устанавливает конкретный шаблон ContentTemplate, содержащий определенный пользовательский элемент управления.
Пользовательский контроль был показан правильно, но его DataContext всегда был нулевым. Поэтому мне пришлось установить контекст ContentControl на: Content="{Binding}"
После этого UserControls работали нормально и имели тот же DataContext, что и их родитель.
Итак, мой XAML выглядит так:
В части Ресурсы я определил два DataTemplates; каждый для каждого UserControl, который я хочу показать.
<DataTemplate x:Key="ViewA">
<namespace:UserControlA/>
</DataTemplate>
<DataTemplate x:Key="ViewB">
<namespace:UserControlB/>
</DataTemplate>
Часть, где я показываю UserControl в зависимости от свойства, выглядит следующим образом:
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Property}" Value="0">
<Setter Property="ContentControl.ContentTemplate" Value="{StaticResource ViewA}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Property}" Value="1">
<Setter Property="ContentControl.ContentTemplate" Value="{StaticResource ViewB}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Прочитав этот вопрос и предыдущие ответы, я предпочитаю использовать ContentControl с содержимым, инициируемым данными:
Элементы управления, которые будут установлены как ContentControl:
<TextBox x:Key="ViewA">
...
</TextBox>
<ComboBox x:Key="ViewB">
...
</ComboBox>
ContentControl, который переключает собственный контент с помощью DataTrigger в стиле ContentControl:
<ContentControl>
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Property}" Value="0">
<Setter Property="Content" Value="{StaticResource ViewA}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Property}" Value="1">
<Setter Property="Content" Value="{StaticResource ViewB}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Я надеюсь, что это помогает кому-то, как предыдущие ответы мне.