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

Ответ

В 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-поиска или валидации.

Ответ 18+ 🔞

Ну что за дичь, блядь! Опять эти режимы привязки, а? Сидишь, такой, пишешь приложение, а оно нихера не работает — данные в одну сторону текут, а обратно нихуя. Знакомо? А всё потому, что не въехал в эти моды, как они там, блядь, называются.

Смотри, есть у нас, сука, пять основных режимов, как пять пальцев, но не все одинаково полезны.

OneWay — это как телевизор, блядь. Ты смотришь на экран, новости там, сериалы, а обратно нихуя не отправишь. Данные идут только от источника (это твоя ViewModel, например) к интерфейсу. Изменил свойство в коде — UI обновился. Ткнул пальцем в TextBlock — нихуя не происходит. Для отображения всякой хуйни, которая не должна меняться с экрана — самое то.

TwoWay — вот это уже диалог, блядь! Полноценный такой. Ты в TextBox вводишь текст — он сразу в свойство летит. Изменил свойство в коде — текст в боксе обновился. Магия, да? Но чтобы эта магия работала, твой источник данных (опять же, ViewModel) должен быть не просто каким-то классом, а уметь кричать на весь мир: «Эй, я изменился, блядь!». Для этого он реализует интерфейс INotifyPropertyChanged. Без этого — будет как разговор с глухонемым: ты ему что-то говоришь, а он тебе в ответ «Муму».

OneTime — это, блядь, как татуха. Сделал один раз при запуске и всё. Никаких обновлений. Засунул туда версию приложения или дату сборки — и похуй. Даже если источник изменится, интерфейс будет сидеть, как истукан, и показывать старое. Для статики, которая не должна меняться в рантайме — идеально.

OneWayToSource — режим наоборот, ёпта! Данные текут не к UI, а от него. Это когда тебе, например, нужно значение слайдера (Slider) запихнуть в свойство, но само свойство слайдеру на отображение не нужно. Редко, но метко используется.

Default — это как автопилот, блядь. Система сама решает, какой режим взять, глядя на то, к какому свойству ты привязываешься. К TextBlock.Text — поставит OneWay. К TextBox.Text — уже TwoWay. Удобно, но если хочешь чёткого контроля — лучше явно указать.

Вот, смотри, как это в коде выглядит, сука:

<StackPanel>
    <!-- OneWay - просто показываем время, ткнуть в него нельзя -->
    <TextBlock Text="{Binding CurrentTime, StringFormat='Часики тикают: {0:HH:mm}'}"/>

    <!-- TwoWay - вот тут уже диалог. Ввёл текст -> свойство обновилось -->
    <TextBox Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

    <!-- OneTime - впендюрили версию и забыли -->
    <TextBlock Text="{Binding AppVersion, Mode=OneTime}"/>

    <!-- OneWayToSource - выбранный элемент из списка летит в свойство -->
    <ListBox ItemsSource="{Binding Items}" 
             SelectedValue="{Binding SelectedItem, Mode=OneWayToSource}"/>
</StackPanel>

И главное, блядь, не забывай про UpdateSourceTrigger для TwoWay! По умолчанию для TextBox источник обновится только когда ты с него уйдёшь (событие LostFocus). А если хочешь, чтобы обновлялось при каждом нажатии клавиши — ставь PropertyChanged. Иначе будешь тыкать, вводить, а данные в модель полетят только когда поле отпустишь.

А без INotifyPropertyChanged в TwoWay-привязках — это просто пиздец, а не разработка. Будешь как тот Герасим из рассказа: «Муму! Муму!», а в ответ — тишина, блядь. UI меняться не будет, когда свойство обновится из кода.

public class MainViewModel : INotifyPropertyChanged
{
    private string _userName;
    public string UserName
    {
        get => _userName;
        set
        {
            if (_userName != value)
            {
                _userName = value;
                OnPropertyChanged(); // Кричим на весь интерфейс: "Я ИЗМЕНИЛСЯ, ЁПТА!"
            }
        }
    }
    // ... остальная реализация INotifyPropertyChanged
}

Вот и вся философия, блядь. Выбирай режим под задачу, не забывай про уведомления, и будет тебе счастье, а не баг на три дня дебага.