Приведи примеры использования разных видов привязки данных (Binding Mode) в WPF

«Приведи примеры использования разных видов привязки данных (Binding Mode) в WPF» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В WPF механизм привязки данных (Data Binding) поддерживает несколько режимов (Mode), которые определяют направление потока данных. Выбор режима критически важен для корректного поведения UI.

Доступные режимы (System.Windows.Data.BindingMode):

Режим Назначение Типичное использование
OneWay Данные идут от источника к цели. Изменения в цели (UI) не обновляют источник. Отображение текста, изображений, «только для чтения».
TwoWay Двусторонняя привязка. Изменения в источнике и цели синхронизируются. Элементы ввода: TextBox, Slider, CheckBox.
OneTime Привязка происходит один раз при инициализации. Последующие изменения в источнике игнорируются. Статические данные, которые не меняются во время работы (например, версия приложения).
OneWayToSource Обратный OneWay. Данные идут от цели к источнику. Когда нужно обновить источник на основе значения UI-элемента, который сам не отображает данные (например, Slider как элемент управления).
Default Режим по умолчанию, который зависит от свойства зависимости цели. Для TextBlock.Text это OneWay, для TextBox.TextTwoWay.

Практические примеры в XAML:

<Window x:Class="BindingExample.MainWindow" ...
        xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <StackPanel>
        <!-- OneWay (по умолчанию для TextBlock) -->
        <TextBlock Text="{Binding CurrentTime, StringFormat='Текущее время: {0:HH:mm:ss}'}"/>

        <!-- TwoWay (обязателен для элементов ввода) -->
        <TextBox Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <CheckBox IsChecked="{Binding IsAgreed, Mode=TwoWay}" Content="Согласен"/>
        <Slider Value="{Binding Volume, Mode=TwoWay}" Minimum="0" Maximum="100"/>

        <!-- OneTime -->
        <TextBlock Text="{Binding AppVersion, Mode=OneTime}"/>
        <TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, 
                           StringFormat='Дата запуска: {0:dd.MM.yyyy}', Mode=OneTime}"/>

        <!-- OneWayToSource -->
        <!-- Источник SelectedValue обновляется, когда меняется выбор в ListBox -->
        <ListBox ItemsSource="{Binding Items}" 
                 SelectedValue="{Binding SelectedItem, Mode=OneWayToSource}"/>
    </StackPanel>
</Window>

Ключевой аспект для TwoWay и OneWayToSource: Чтобы изменения, инициированные UI, передавались обратно в источник данных (например, в ViewModel), источник должен реализовывать интерфейс INotifyPropertyChanged.

public class MainViewModel : INotifyPropertyChanged
{
    private string _userName;
    public string UserName
    {
        get => _userName;
        set
        {
            if (_userName != value)
            {
                _userName = value;
                OnPropertyChanged(); // Это уведомляет UI об изменении
            }
        }
    }
    // ... реализация INotifyPropertyChanged и другие свойства
}

UpdateSourceTrigger: Для TwoWay привязок важно свойство UpdateSourceTrigger, которое определяет, когда обновлять источник. По умолчанию для TextBox.Text это LostFocus. Установка PropertyChanged (как в примере выше) заставляет источник обновляться при каждом нажатии клавиши, что часто используется для live-поиска или валидации.