Поиск…


Синтаксис

  • {Binding PropertyName} эквивалентно {Binding Path = PropertyName}
  • {Binding Path = SomeProperty.SomeOtherProperty.YetAnotherProperty}
  • {Binding Path = SomeListProperty [1]}

параметры

параметр подробности
Дорожка Указывает путь для привязки. Если не указано, привязывается к самому DataContext.
UpdateSourceTrigger Указывает, когда источник привязки обновлен. По умолчанию для LostFocus . Наиболее используемым значением является PropertyChanged .
Режим Обычно OneWay или TwoWay . Если это не указано в привязке, по умолчанию используется значение OneWay если целевой объект привязки не запрашивает его как TwoWay . Произошла ошибка, когда TwoWay используется для привязки к свойству readonly, например, OneWay должен быть явно установлен при привязке свойства readonly string к TextBox.Text .
Источник Позволяет использовать StaticResource в качестве источника привязки вместо текущего DataContext.
RelativeSource Позволяет использовать другой элемент XAML в качестве источника привязки вместо текущего DataContext.
ElementName Позволяет использовать именованный элемент XAML в качестве источника привязки вместо текущего DataContext.
FallbackValue Если привязка не выполняется, это значение предоставляется целевой привязке.
TargetNullValue Если значение источника привязки равно null , это значение указывается в целевой привязке.
конвертер Указывает преобразователь StaticResource который используется для преобразования значения привязки, например, конвертировать логическое значение в элемент перечисления Visibility .
ConverterParameter Задает необязательный параметр, который должен быть предоставлен преобразователю. Это значение должно быть статическим и не может быть связано.
StringFormat Указывает строку формата, которая будет использоваться при отображении связанного значения.
задержка (WPF 4.5+) Задает задержка в milliseconds для привязки для обновления BindingSource в ViewModel . Это необходимо использовать с Mode=TwoWay и UpdateSourceTrigger=PropertyChanged для вступления в силу.

замечания

UpdateSourceTrigger

По умолчанию WPF обновляет источник привязки, когда управление теряет фокус. Однако, если есть только один элемент управления, который может получить фокус - что-то общее в примерах - вам нужно будет указать UpdateSourceTrigger=PropertyChanged для обновлений, которые будут работать.

Вы захотите использовать PropertyChanged в качестве триггера для многих двусторонних привязок, если обновление источника привязки при каждом нажатии клавиши не является дорогостоящим, или проверка достоверности данных нежелательна.

Использование LostFocus имеет неприятный побочный эффект: нажав enter, чтобы отправить форму, используя кнопку, отмеченную IsDefault , не обновляет свойство, поддерживающее вашу привязку, эффективно отменяя ваши изменения. К счастью, существуют некоторые обходные пути .

Также обратите внимание, что в отличие от UWP, WPF (4.5+) также имеет свойство Delay в привязках, которого может быть достаточно для некоторых привязок с локальными или просто небольшими настройками интеллекта, такими как некоторые проверки TextBox .

Преобразование значения типа boolean в значение видимости

В этом примере скрывается красная рамка (граница), если флажок не проверяется с помощью IValueConverter .

Примечание . BooleanToVisibilityConverter используемый в приведенном ниже примере, представляет собой встроенный преобразователь значений, расположенный в пространстве имен System.Windows.Controls.

XAML:

<Window x:Class="StackOverflowDataBindingExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
    </Window.Resources>
    <StackPanel>
        <CheckBox x:Name="MyCheckBox"
                  IsChecked="True" />
        <Border Background="Red" Width="20" Height="20"
                Visibility="{Binding Path=IsChecked,ElementName=MyCheckBox, Converter={StaticResource VisibleIfTrueConverter}}" />
    </StackPanel>
</Window>

Определение DataContext

Чтобы работать со связями в WPF, вам необходимо определить DataContext . DataContext сообщает привязки, где по умолчанию получают свои данные.

<Window x:Class="StackOverflowDataBindingExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:StackOverflowDataBindingExample"
        xmlns:vm="clr-namespace:StackOverflowDataBindingExample.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:HelloWorldViewModel />
    </Window.DataContext>
    ...
</Window>

Вы также можете установить DataContext с помощью кода, но стоит отметить, что XAML IntelliSense несколько придирчив: в XAML для IntelliSense должен быть установлен строго типизированный DataContext, чтобы предлагать свойства, доступные для привязки.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new HelloWorldViewModel();
    }
}

Хотя существуют рамки, которые помогут вам более точно определить ваш DataContext (например, MVVM Light имеет локатор viewmodel, который использует инверсию управления ), мы используем быстрый и грязный метод для целей этого руководства.

Вы можете определить DataContext практически для любого визуального элемента в WPF. DataContext обычно унаследован от предков в визуальном дереве, если он явно не переопределен, например, внутри ContentPresenter.

Внедрение INotifyPropertyChanged

INotifyPropertyChanged - это интерфейс, используемый источниками привязки (то есть DataContext), чтобы пользовательский интерфейс или другие компоненты знали, что свойство было изменено. WPF автоматически обновляет пользовательский интерфейс для вас, когда он видит событие PropertyChanged . Желательно, чтобы этот интерфейс реализован в базовом классе, который могут наследовать все ваши модели просмотра.

В C # 6 это все, что вам нужно:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Это позволяет вам вызывать NotifyPropertyChanged двумя разными способами:

  1. NotifyPropertyChanged() , который поднимет событие для вызывающего устройства, которое вызывает его, благодаря атрибуту CallerMemberName .
  2. NotifyPropertyChanged(nameof(SomeOtherProperty)) , который поднимет событие для SomeOtherProperty.

Для .NET 4.5 и выше с использованием C # 5.0 это можно использовать вместо этого:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] string name = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

В версиях .NET до 4.5 вам нужно определить имена свойств как строковые константы или решение с использованием выражений .


Примечание. Можно привязать свойство «обычного старого объекта C #» (POCO), которое не реализует INotifyPropertyChanged и наблюдать, что привязки работают лучше, чем ожидалось. Это скрытая функция в .NET, и ее, вероятно, следует избегать. Тем более , что это приведет к утечке памяти , когда связывание - х Mode не OneTime (см здесь ).

Почему обновление привязки не реализует INotifyPropertyChanged?

Привязать к свойству другого именованного элемента

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

<StackPanel>
    <CheckBox x:Name="MyCheckBox" IsChecked="True" />
    <TextBlock Text="{Binding IsChecked, ElementName=MyCheckBox}" />
</StackPanel>

Привязать к собственности предка

Вы можете привязать свойство предка в визуальном дереве с помощью привязки RelativeSource . Ближайший элемент управления, расположенный выше в визуальном дереве, который имеет тот же тип или получен из указанного вами типа, будет использоваться в качестве источника привязки:

<Grid Background="Blue">
    <Grid Background="Gray" Margin="10">
        <Border Background="Red" Margin="20">
            <StackPanel Background="White" Margin="20">
                <Button Margin="10" Content="Button1" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />
                <Button Margin="10" Content="Button2" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}" />
            </StackPanel>
        </Border>
    </Grid>
</Grid>

В этом примере Button1 имеет серый фон, поскольку ближайший предок Grid имеет серый фон. Button2 имеет белый фон, потому что ближайшим предком, полученным из FrameworkElement является белый StackPanel .

Пример привязки RelativeSource

Связывание нескольких значений с помощью MultiBinding

MultiBinding позволяет привязать несколько значений к одному и тому же свойству. В следующем примере несколько значений привязаны к свойству Text текстового поля и отформатированы с использованием свойства StringFormat.

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0} {1}">
            <Binding Path="User.Forename"/>
            <Binding Path="User.Surname"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Помимо StringFormat , IMultiValueConverter также может использоваться для преобразования значений из привязок в одно значение для цели MultiBinding.

Однако MultiBindings не может быть вложенным.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow