Для чего нужен DataContext?
В качестве продолжения вопроса Связывание DataContext с другим свойством в WPF.
В самом конце исследования я был очень удивлен, узнав, что, когда вы пишете что-то вроде этого:
<Label Content="{Binding Path=Name}" />
DataContext
, с которым привязан свойство Content
, принадлежит самому элементу Label
! Тот факт, что он все еще работает, связан с наследованием по умолчанию значения DataContext от ближайшего родителя.
Но если у вас есть этот ярлык, завернутый в пользовательский элемент управления, и вы не хотите привязывать свои данные к свойству DataContext
этого элемента управления, вам скорее всего понравится:
<Controls:SearchSettings Settings="{Binding Path=Settings}" />
И вот вы. Теперь вам нужно установить Settings
как DataContext
для элемента управления SearchSettings
, для Label
внутри для привязки, но вы не можете, потому что это вызовет повторное связывание свойства Settings
.
Я не вижу смысла смешивать свойства связывания с использованием разных источников: DataContext
, ElementName
и т.д.
Так почему бы мне использовать DataContext
?
Ответы
Ответ 1
Когда вы пишете
<Label name="myLabel" Content="{Binding Path=Name}" />
вы привязываетесь к myLabel.DataContext.Name
, а не myLabel.Name
.
XAML в WPF - это просто удобный пользовательский интерфейс для отображения и взаимодействия с фактическими данными, иначе известный как DataContext
. Цель других источников привязки (RelativeSource
, ElementName
и т.д.) Заключается в том, чтобы указать на другое свойство, которое не существует в текущем элементе управления DataContext
Предположим, у вас есть окно. Без установки DataContext окно все еще отображается, но за ним нет данных.
Предположим теперь, чтобы установить myWindow.DataContext = new ClassA();
. Теперь данные, отображаемые в окне, ClassA
. Если ClassA
имеет свойство, называемое Name
, я мог бы написать метку и привязать ее к Name
(например, вашему примеру), и любое значение, хранящееся в ClassA.Name
, будет отображаться.
Теперь предположим, что ClassA
имеет свойство ClassB
, и оба класса имеют свойство, называемое Name
. Вот блок XAML, который иллюстрирует цель DataContext, и пример того, как элемент управления будет ссылаться на свойство, а не на него собственный DataContext
<Window x:Name="myWindow"> <!-- DataContext is set to ClassA -->
<StackPanel> <!-- DataContext is set to ClassA -->
<!-- DataContext is set to ClassA, so will display ClassA.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassA, however we are setting it to ClassA.ClassB -->
<StackPanel DataContext="{Binding ClassB}">
<!-- DataContext is set to ClassB, so will display ClassB.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassB, but we are binding to the Window DataContext.Name which is ClassA.Name -->
<Label Content="{Binding ElementName=myWindow, Path=DataContext.Name}" />
</StackPanel>
</StackPanel>
</Window>
Как вы можете видеть, DataContext основан на любых данных, находящихся за объектом пользовательского интерфейса.
Обновление: Я так часто вижу этот вопрос у новых пользователей WPF, что я расширил этот ответ в сообщении в своем блоге: Что это "DataContext" , о котором вы говорите?
Ответ 2
В этом конкретном случае вы можете сделать:
<Controls:SearchSettings DataContext="{Binding Path=Settings}" Settings="{Binding}" />
Предполагая, что вы хотите, чтобы все содержимое ContentSettings содержало настройки в качестве контекста данных. В принципе, DataContext влияет на сам элемент как на потомков, которые явно не переопределяют его.
Ответ 3
От CodeProject от kishore Gaddam:
DataContext
является одним из наиболее фундаментальных понятий в привязке данных. Объект Binding должен получить свои данные откуда-то, и есть несколько способов указать источник данных, например, использовать свойство Source непосредственно в Binding, наследуя DataContext
от ближайшего элемента при прохождении в дереве, установив свойства ElementName
и RelativeSource
в объекте Binding.
Подробный пример в CodeProject: http://www.codeproject.com/Articles/321899/DataContext-in-WPF
Ответ 4
В большинстве случаев вы хотите привязываться к DataContext, в некоторых шаблонах на ItemsControls это единственный способ привязки к обычному шаблону, например. Дальнейшие привязки к DataContext приятно писать и читать, поскольку они кратки.
В вашем примере вы все равно можете установить DataContext, вам нужно только изменить привязку в настройках соответственно:
<Controls:SearchSettings DataContext="{Binding Settings}" Settings="{Binding}"/>