Установка DataContext в UserControl влияет на привязки в родительском - PullRequest
12 голосов
/ 27 сентября 2011

У меня есть базовый UserControl, который устанавливает для себя DataContext для простоты привязки:

<UserControl x:Class="MyControlLib.ChildControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

             DataContext="{Binding RelativeSource={RelativeSource Self}}">

</UserControl>

Используется в родительском XAML-файле, например:

<UserControl x:Class="MyControlLib.ParentControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:ctrl="clr-namespace:MyControlLib">

             <ctrl:ChildControl x:Name="ChildName" 
                                PropertyOnChild="{Binding PropertyInParentContext}"/>             
</UserControl>

По какой-то причине это приводит к ошибке привязки, которая, по-видимому, указывает на то, что на DataContext родительского элемента управления влияет собственный дочерний элемент управления DataContext.

System.Windows.Data Ошибка: 40: Ошибка пути BindingExpression: свойство 'PropertyInParentContext' не найдено в 'объекте' '' ChildControl '(Name =' ChildName ')'. BindingExpression: Path = PropertyInParentContext; DataItem = 'ChildControl' (Name = 'ChildName'); Целевым элементом является ChildControl (Name = ChildName); Целевым свойством является «PropertyOnChild» (введите «что угодно»)

Почему «PropertyInParentContext» ищется в дочернем элементе управления, а не в родительском элементе DataContext?

Если я уберу

DataContext="{Binding RelativeSource={RelativeSource Self}}

от контроля детей, тогда все работает так, как я ожидал.

Я что-то упускаю здесь очевидное?

Ответы [ 2 ]

11 голосов
/ 27 сентября 2011

Объявление вашего элемента управления и создания экземпляров в основном манипулируют одним и тем же объектом, все свойства, установленные в объявлении, также устанавливаются для каждого экземпляра.Таким образом, если свойства были «видимыми», так сказать:

<UserControl x:Class="MyControlLib.ParentControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:ctrl="clr-namespace:MyControlLib">
    <ctrl:ChildControl x:Name="ChildName" 
                       DataContext="{Binding RelativeSource={RelativeSource Self}}"
                       PropertyOnChild="{Binding PropertyInParentContext}"/>
</UserControl>

Вот почему вы не устанавливаете DataContext из UserControls, он будет переопределять унаследованный DataContext (и даже запутыватьДело в том, что есть другой контекст).Если вы хотите связать со свойствами UserControl в его объявлении, назовите элемент управления и используйте вместо него ElementName или RelativeSource -привязки.

5 голосов
/ 27 сентября 2011

Self означает UserControl, поэтому, когда вы устанавливаете DataContext на Self, вы устанавливаете DataContext для объекта UserControl.

Правильный синтаксис для привязки к DataContext элемента управления будет {Binding RelativeSource={RelativeSource Self}, Path=DataContext}, однако, поскольку DataContext наследуется Родителем, эта привязка совершенно не нужна в любой ситуации.

Кроме того, если вы связываете DataContext с Self.DataContext, вы, по сути, создадите цикл, в котором значение привязано к самому себе.

...