Как работает привязка данных (Binding) в WPF и что такое DataContext?
Везде в WPF пишут {Binding SomeProperty}, но откуда контрол берёт эти данные? Что такое DataContext и как вообще устроена привязка данных в WPF? Хочу понять механику, а не копировать примеры.
2 ответа
Привязка данных (Binding) — это механизм, который автоматически связывает свойство элемента UI со свойством объекта-источника. Когда меняется источник — обновляется UI (и наоборот).
Источник данных берётся из DataContext — это свойство, которое наследуется вниз по дереву элементов. Если вы задали DataContext у окна, его «видят» все вложенные контролы.
Пример. Есть класс-источник:
public class Person
{
public string Name { get; set; } = "Иван";
public int Age { get; set; } = 30;
}
Задаём его как DataContext в код-бихайнде:
public MainWindow()
{
InitializeComponent();
DataContext = new Person(); // источник для всего окна
}
Теперь в XAML привязываемся к свойствам без указания объекта — берётся из DataContext:
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBox Text="{Binding Age, Mode=TwoWay}"/>
</StackPanel>
Важные режимы привязки (Mode):
OneWay— источник → UI (только чтение);TwoWay— в обе стороны (для полей ввода);OneTime— один раз при загрузке.
Есть и другие способы указать источник вместо DataContext:
<!-- привязка к другому элементу по имени -->
<TextBlock Text="{Binding ElementName=mySlider, Path=Value}"/>
<!-- привязка к свойству самого контрола -->
<TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth}"/>
Главное правило: контрол смотрит на свой DataContext (или явно указанный источник) и берёт оттуда свойство по Path. Чтобы UI обновлялся при изменении данных, источник должен реализовывать INotifyPropertyChanged — но это уже отдельная тема.
Хочу подчеркнуть момент, на котором спотыкаются почти все новички: если вы задали DataContext, но UI не обновляется при изменении данных в коде — значит источник не уведомляет об изменениях. Сам по себе Binding отслеживает только изменения через INotifyPropertyChanged или DependencyProperty. Простой get/set без уведомления = одноразовое отображение. Об этом стоит помнить сразу.