Поделиться через


Подробная привязка данных Windows

В этой статье описываются функции привязки данных WinUI с помощью API в пространстве имен Microsoft.UI.Xaml.Data.

Замечание

В этом разделе подробно описаны функции привязки данных. Краткое практическое введение см. в обзоре привязки данных.

Важные API

Введение

Привязка данных — это метод, позволяющий пользовательскому интерфейсу приложения эффективно отображать и синхронизировать данные. Разделив проблемы с данными от проблем пользовательского интерфейса, она упрощает проектирование приложения, повышает удобочитаемость и повышает удобство обслуживания.

Привязка данных позволяет просто отображать значения из источника данных при первом отображении пользовательского интерфейса, но не реагировать на изменения этих значений. Этот режим привязки называется однократным, и он хорошо подходит для значения, которое не изменяется во время выполнения. Кроме того, можно выбрать "наблюдать" значения и обновлять пользовательский интерфейс при их изменении. Этот режим называется односторонним, и он хорошо подходит для данных только для чтения. В конечном счете можно выбрать как наблюдать, так и обновлять, чтобы изменения, внесенные пользователем в значения в пользовательском интерфейсе, автоматически отправляются обратно в источник данных. Этот режим называется двусторонним, и он хорошо подходит для данных чтения и записи. Ниже приведены некоторые примеры.

  • Вы можете использовать одноразовый режим для привязки изображения к фотографии текущего пользователя.
  • Вы можете использовать односторонний режим для привязки ListView к коллекции новостей в режиме реального времени, сгруппированных по разделу газеты.
  • Вы можете использовать двусторонний режим для привязки TextBox к имени клиента в форме.

Независимо от режима, существует два типа привязки, и обычно вы объявляете оба в разметке пользовательского интерфейса. Вы можете использовать расширение разметки {x:Bind} или расширение разметки {Binding}. Вы даже можете использовать смесь двух в одном приложении, даже в одном элементе пользовательского интерфейса. {x:Bind} был новым в UWP для Windows 10 и имеет лучшую производительность. Все сведения, описанные в этом разделе, применяются к обоим типам привязки, если мы явно не говорим в противном случае.

Примеры приложений UWP, демонстрирующие {x:Bind}

Примеры приложений UWP, демонстрирующие {Binding}

Каждая привязка включает в себя эти части

  • Источник привязки. Этот источник предоставляет данные для привязки. Это может быть экземпляр любого класса с элементами, значения которых необходимо отобразить в пользовательском интерфейсе.
  • Целевой объект привязки. Этот целевой элемент — свойство зависимости элемента FrameworkElement в пользовательском интерфейсе, где отображаются данные.
  • Объект привязки. Этот объект передает значения данных из источника в целевой объект и при необходимости из целевого объекта обратно в источник. Объект привязки создается во время загрузки XAML из расширения разметки {x:Bind} или {Binding} .

В следующих разделах вы внимательно изучите источник привязки, целевой объект привязки и объект привязки. Разделы связываются вместе с примером привязки содержимого кнопки к строковому свойству, которому принадлежит класс с именемNextButtonTextHostViewModel.

Источник привязки

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

public class HostViewModel
{
    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText { get; set; }
}

Эта реализация HostViewModelи его свойство NextButtonTextработают только для однократной привязки. Но односторонняя и двусторонняя привязка крайне распространена. В таких типах привязки пользовательский интерфейс автоматически обновляется в ответ на изменения значений данных источника привязки. Чтобы эти типы привязки работали правильно, необходимо сделать источник привязки наблюдаемым для объекта привязки. Поэтому в нашем примере, если требуется односторонняя или двусторонняя привязка к свойству NextButtonText, необходимо обеспечить, чтобы все изменения значения этого свойства, происходящие во время выполнения, были заметны объекту привязки.

Один из способов сделать это — унаследовать класс, представляющий ваш источник привязки, от `DependencyObject` и предоставить значение данных через `DependencyProperty*`. Вот как FrameworkElement становится наблюдаемым. Это FrameworkElement хороший источник привязки прямо из поля.

Более упрощенный способ создания наблюдаемого класса (и необходимого для классов, у которых уже есть базовый класс), — реализовать System.ComponentModel.INotifyPropertyChanged. Этот подход включает реализацию одного события с именем PropertyChanged. Пример использования HostViewModel показан в следующем коде.

...
using System.ComponentModel;
using System.Runtime.CompilerServices;
...
public class HostViewModel : INotifyPropertyChanged
{
    private string nextButtonText;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return nextButtonText; }
        set
        {
            nextButtonText = value;
            OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

NextButtonText Теперь свойство наблюдаемо. При создании односторонняя или двусторонняя привязка к такому свойству (мы покажем, как позже), результирующий объект привязки подписывается на PropertyChanged событие. При возникновении этого события обработчик объекта привязки получает аргумент, содержащий имя измененного свойства. Вот как объект привязки знает, какое значение свойства нужно прочитать снова.

Таким образом, вам не нужно реализовать шаблон, показанный ранее несколько раз, если вы используете C#, вы можете получить производный от BindableBase базового класса, который вы найдете в примере QuizGame (в папке Common). Ниже приведен пример того, как это выглядит.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return nextButtonText; }
        set { SetProperty(ref nextButtonText, value); }
    }
}

PropertyChanged Вызов события с аргументом String.Empty или null указывает, что все неиндексируемые свойства объекта должны быть прочитаны заново. Событие можно вызвать, чтобы указать, что свойства индексатора объекта изменились, используя аргумент Item[indexer], для определенных индексаторов (где индексатор является значением индекса), или значение "Item[]" для всех индексаторов.

Источник привязки можно рассматривать как один объект, свойства которого содержат данные, или как коллекцию объектов. В коде C# можно однократно привязаться к объекту, реализующего list<T> , чтобы отобразить коллекцию, которая не изменяется во время выполнения. Для наблюдаемой коллекции, чтобы отслеживать добавление и удаление элементов, используйте одностороннюю привязку к ObservableCollection<T>. Чтобы выполнить привязку к собственным классам коллекции, используйте инструкции в следующей таблице.

Scenario C# (CLR) C++/WinRT
Привязка к объекту. Может быть любым объектом. Может быть любым объектом.
Получение уведомлений об изменении свойства из привязанного объекта. Объект должен реализовать INotifyPropertyChanged. Объект должен реализовать INotifyPropertyChanged.
Привязка к коллекции. Список<T> IVectorIInspectable или IBindableObservableVector. См. элементы управления XAML; привязка к коллекции C++/WinRT и коллекциям с помощью C++/WinRT.
Получение уведомлений об изменении коллекции из связанной коллекции. ObservableCollection<T> IObservableVectorиз IInspectable. Например, winrt::single_threaded_observable_vector<T>.
Реализуйте коллекцию, поддерживающую привязку. Расширять List<T> или реализовывать IList, IList<Object>, IEnumerable или IEnumerable<Object>. Привязка к обобщенному IList<T> и IEnumerable<T> не поддерживается. Реализуйте IVector для IInspectable. См. элементы управления XAML; привязка к коллекции C++/WinRT и коллекциям с помощью C++/WinRT.
Реализуйте коллекцию, которая поддерживает уведомления об изменении коллекции. Расширьте ObservableCollection<T> или реализуйте (необобщённый) IList и INotifyCollectionChanged. Реализуйте IObservableVector из IInspectable или IBindableObservableVector.
Реализуйте коллекцию, которая поддерживает добавочную загрузку. Расширьте ObservableCollection<T> или реализуйте (не универсальный) IList и INotifyCollectionChanged. Кроме того, реализуйте ISupportIncrementalLoading. Реализуйте IObservableVector от IInspectable или IBindableObservableVector. Кроме того, реализуйте ISupportIncrementalLoading

Можно привязать элементы управления списка к произвольным большим источникам данных и обеспечить высокую производительность с помощью добавочной загрузки. Например, можно привязать элементы управления списками к результатам запроса изображений Bing, не загружая все результаты одновременно. Вместо этого вы загружаете только некоторые результаты немедленно и загружаете дополнительные результаты по мере необходимости. Для поддержки добавочной загрузки необходимо реализовать ISupportIncrementalLoading в источнике данных, поддерживающем уведомления об изменении коллекции. Когда подсистема привязки данных запрашивает больше данных, источник данных должен выполнять соответствующие запросы, интегрировать результаты, а затем отправлять соответствующие уведомления для обновления пользовательского интерфейса.

Целевой объект привязки

В следующих двух примерах свойство Button.Content является целевым объектом привязки. Его значение установлено в расширение разметки, которое объявляет объект привязки. Первый пример показывает {x:Bind}, а второй пример — {Binding}. Объявление привязок в разметке является обычной практикой, так как это удобно, читаемо и легко обрабатывается инструментами. Но если вам нужно, можно избежать разметки и принудительно (программно) создать экземпляр класса Binding .

<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />

Если вы используете C++/WinRT, необходимо добавить атрибут BindableAttribute в любой класс среды выполнения, с которым вы хотите использовать расширение разметки {Binding} .

Это важно

Если вы используете C++/WinRT, атрибут BindableAttribute доступен с помощью пакета SDK для приложений Windows. Без этого атрибута необходимо реализовать интерфейсы ICustomPropertyProvider и ICustomProperty , чтобы использовать расширение разметки {Binding} .

Объект привязки, объявленный с помощью {x:Bind}

Перед созданием разметки {x:Bind} необходимо предоставить исходный класс привязки из класса, представляющего страницу разметки. Добавьте свойство (типа HostViewModel в данном случае) в MainWindow класс окна.

namespace DataBindingInDepth
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}

После добавления свойства можно более подробно ознакомиться с разметкой, объявляющей объект привязки. В следующем примере используется тот же Button.Content целевой объект привязки, который вы видели в разделе "Целевая привязка" ранее. В нем показан целевой объект привязки, привязанный к свойству HostViewModel.NextButtonText .

<!-- MainWindow.xaml -->
<Window x:Class="DataBindingInDepth.MainWindow" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Window>

Обратите внимание на указанное значение Path. Окно интерпретирует это значение в собственном контексте. В этом случае путь начинается с ссылки на ViewModel свойство, которое вы только что добавили на страницу MainWindow . Это свойство возвращает экземпляр HostViewModel, чтобы иметь возможность использовать точечную нотацию для доступа к свойству HostViewModel.NextButtonText этого объекта. Вы указываете Mode, чтобы переопределить значение {x:Bind}, используемое по умолчанию однократно.

Свойство Path поддерживает различные варианты синтаксиса привязки к вложенным свойствам, присоединенным свойствам и целым числам и строковым индексаторам. Дополнительные сведения см. в разделе "Синтаксис пути свойства". Привязка к строковым индексаторам дает эффект привязки к динамическим свойствам без реализации ICustomPropertyProvider. Сведения о других параметрах см. в разделе {x:Bind}.

Чтобы показать, что свойство HostViewModel.NextButtonText наблюдаемо, добавьте обработчик события Click к кнопке и обновите значение HostViewModel.NextButtonText. Выполните сборку, запустите и нажмите кнопку, чтобы увидеть значение обновления кнопки Content .

// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    ViewModel.NextButtonText = "Updated Next button text";
}

Замечание

Изменения в TextBox.Text отправляются в источник, привязанный по обоим направлениям, когда TextBox теряет фокус, а не после каждого нажатия клавиши.

DataTemplate и x:DataType

Внутри DataTemplate (вне зависимости от того, используется ли она как шаблон элемента, содержимого или заголовка) значение Path не интерпретируется в контексте окна. Вместо этого он работает в контексте объекта данных, с которым вы создаёте шаблон. При использовании {x:Bind} в шаблоне данных можно проверить привязки во время компиляции и создать эффективный код для них. Для этого DataTemplate необходимо объявить тип объекта данных с помощью x:DataType. Следующий пример можно использовать в качестве ItemTemplate элемента управления элементами, привязанным к коллекции SampleDataGroup объектов.

<DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Слабо типизированные объекты в пути

Предположим, у вас есть тип, SampleDataGroup который реализует строковое свойство с именем Title. У вас также есть свойство MainWindow.SampleDataGroupAsObject типа object, но фактически возвращает экземпляр SampleDataGroup. Привязка <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> приводит к ошибке компиляции, так как Title свойство не найдено в типе object. Чтобы исправить эту ошибку, добавьте приведение в ваш Path синтаксис следующим образом: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Вот еще один пример, где Element объявляется какobject, но на самом деле TextBlock<TextBlock Text="{x:Bind Element.Text}"/>: . Каст устраняет проблему: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>

Если данные загружаются асинхронно

Частичные классы для Windows создают код для поддержки {x:Bind} во время компиляции. Эти файлы можно найти в obj папке с такими именами, как (для C#). <view name>.g.cs Созданный код содержит обработчик события загрузки окна. Этот обработчик вызывает Initialize метод в созданном классе, представляющем привязки окна. Initialize вызовы Update для начала перемещения данных между источником привязки и целевым объектом. Loading вызывается непосредственно перед первым прохождением меры окна или пользовательского элемента управления. Если данные загружаются асинхронно, к моменту вызова Initialize они могут быть не готовы. После загрузки данных можно принудительно инициализировать однократные привязки путем вызова this.Bindings.Update();. Если вам нужны только однократные привязки для асинхронно загруженных данных, это гораздо дешевле инициализировать их таким образом, чем иметь односторонние привязки и прослушивать изменения. Если ваши данные не подвергаются детализированным изменениям и, скорее всего, будут обновляться в рамках определенного действия, вы можете выполнить однократную установку привязок и принудительно обновить данные в любое время, вызвав Update.

Замечание

{x:Bind} Не подходит для сценариев с поздней привязкой, таких как навигация по структуре словаря объекта JSON, а также для ввода текста утки. "Дак ввод" является слабой формой ввода на основе лексических совпадений по именам свойств (как в, "если он идет, плавает, и квак, как утка, то это утка"). При вводе утки привязка к Age свойству будет одинаково удовлетворена Person объектом или Wine объектом (при условии, что эти типы имеют Age свойство). Для этих сценариев используйте {Binding} расширение разметки.

Объект привязки, объявлённый с помощью {Binding}

Если вы используете C++/WinRT, добавьте атрибут BindableAttribute в любой класс среды выполнения, к которому необходимо привязаться при использовании расширения разметки {Binding} . Чтобы использовать {x:Bind}, этот атрибут не нужен.

// HostViewModel.idl
// Add this attribute:
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
    HostViewModel();
    String NextButtonText;
}

Это важно

Если вы используете C++/WinRT, атрибут BindableAttribute доступен с помощью пакета SDK для приложений Windows. Без этого атрибута необходимо реализовать интерфейсы ICustomPropertyProvider и ICustomProperty , чтобы использовать расширение разметки {Binding} .

По умолчанию {Binding} предполагает, что вы привязываетесь к DataContext окна разметки. Таким образом, установите DataContext вашего окна в качестве экземпляра вашего класса источника привязки (типа HostViewModel в данном случае). В следующем примере показана разметка, которая объявляет объект привязки. Он использует тот же Button.Content целевой объект привязки, используемый в разделе "Целевой объект привязки" ранее, и он привязывается к свойству HostViewModel.NextButtonText .

<Window xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Window.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Window.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Window>
// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    viewModelInDataContext.NextButtonText = "Updated Next button text";
}

Обратите внимание на значение, указанное для Path. DataContext окна интерпретирует это значение, которое в этом примере задано для экземпляраHostViewModel. Путь ссылается на HostViewModel.NextButtonText свойство. Вы можете опустить Mode, так как здесь работает односторонняя работа {Binding} по умолчанию.

Значение dataContext по умолчанию для элемента пользовательского интерфейса является унаследованным значением родительского элемента. Вы можете переопределить значение по умолчанию, установив явное значение DataContext , которое, в свою очередь, наследуется дочерними элементами по умолчанию. Явное задание DataContext элемента полезно при наличии нескольких привязок, использующих один и тот же источник.

Объект привязки имеет Source свойство, которое по умолчанию соответствует DataContext элемента пользовательского интерфейса, на котором объявлена привязка. Этот параметр по умолчанию можно переопределить по умолчанию SourceRelativeSourceили ElementName явно в привязке (дополнительные сведения см. в разделе {Binding}).

Внутри DataTemplatedataContext автоматически устанавливается для шаблона объекта данных. Следующий пример можно использовать в качестве ItemTemplate элемента управления элементами, привязанным к коллекции любого типа, имеющего строковые свойства с именем Title и Description.

<DataTemplate x:Key="SimpleItemTemplate">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{Binding Title}"/>
      <TextBlock Text="{Binding Description"/>
    </StackPanel>
  </DataTemplate>

Замечание

По умолчанию изменения в TextBox.Text отправляются в двусторонне привязанный источник при потере фокуса TextBox . Чтобы вызвать отправку изменений после каждого нажатия клавиш пользователя, задайте UpdateSourceTrigger для PropertyChanged привязки в разметке. Вы также можете полностью контролировать, когда изменения отправляются в источник, задав для этого значение UpdateSourceTriggerExplicit. Затем вы обрабатываете события в текстовом поле (обычно TextBox.TextChanged), вызываете GetBindingExpression в целевом объекте, чтобы получить объект BindingExpression, и, наконец, вызовите BindingExpression.UpdateSource для программного обновления источника данных.

Свойство Path поддерживает различные варианты синтаксиса привязки к вложенным свойствам, присоединенным свойствам и целым числам и строковым индексаторам. Дополнительные сведения см. в разделе "Синтаксис пути свойства". Привязка к строковым индексаторам дает эффект привязки к динамическим свойствам без реализации ICustomPropertyProvider. Свойство ElementName полезно для привязки элемента к элементу. Свойство RelativeSource имеет несколько вариантов использования, один из которых является более мощной альтернативой привязке шаблона внутри ControlTemplate. Сведения о других параметрах см. в разделе "Расширение разметки {Binding} и класс Binding ".

Что если источник и цель не одного типа?

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

  • При использовании {x:Bind} можно привязать непосредственно к функции для этого преобразования.
  • Или можно указать преобразователь значений, который является объектом, предназначенным для выполнения преобразования.

Преобразователи значений

Ниже приведен преобразователь значений, подходящий для однократной привязки или односторонняя привязка, которая преобразует значение DateTime в string значение, содержащее месяц. Класс реализует IValueConverter.

public class DateToStringConverter : IValueConverter
{
    // Define the Convert method to convert a DateTime value to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // value is the data from the source object.
        DateTime thisDate = (DateTime)value;
        int monthNum = thisDate.Month;
        string month;
        switch (monthNum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;
    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

И вот как вы используете этот преобразователь значений в разметке объекта привязки.

<UserControl.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</UserControl.Resources>
...
<TextBlock Grid.Column="0" 
  Text="{x:Bind ViewModel.Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="0" 
  Text="{Binding Month, Converter={StaticResource Converter1}}"/>

Подсистема привязки вызывает методы Convert и ConvertBack , если параметр Converter определен для привязки. Когда данные передаются из источника, подсистема привязки вызывает Convert и передает возвращенные данные целевому объекту. При передаче данных из целевого объекта (для двусторонней привязки) подсистема привязки вызывает ConvertBack и передает возвращенные данные источнику.

Преобразователь также имеет необязательные параметры: ConverterLanguage, который позволяет указывать язык, используемый в преобразовании, и ConverterParameter, что позволяет передавать параметр для логики преобразования. Пример использования параметра преобразователя см. в разделе IValueConverter.

Замечание

Если в преобразовании возникает ошибка, не вызывайте исключение. Вместо этого возвращает значение DependencyProperty.UnsetValue, которое остановит передачу данных.

Чтобы отобразить значение по умолчанию, используемое всякий раз, когда источник привязки не может быть разрешен, задайте FallbackValue свойство объекта привязки в разметке. Это полезно для обработки ошибок преобразования и форматирования. Также полезно привязать к свойствам источника, которые могут не существовать во всех объектах в связанной коллекции разнородных типов.

Если привязать текстовый элемент управления к значению, которое не является строкой, подсистема привязки данных преобразует значение в строку. Если значение является ссылочным типом, подсистема привязки данных извлекает строковое значение путем вызова ICustomPropertyProvider.GetStringRepresentation или IStringable.ToString , если оно доступно, и в противном случае вызовет Object.ToString. Обратите внимание, что подсистема привязки будет игнорировать любую ToString реализацию, которая скрывает реализацию базового класса. Вместо этого реализации подклассов следует переопределить метод базового класса ToString . Аналогичным образом, на собственных языках все управляемые объекты, как представляется, реализуют ICustomPropertyProvider и IStringable. Однако все вызовы GetStringRepresentation и IStringable.ToString перенаправлены в Object.ToString этот метод или переопределение этого метода, и никогда не в новую ToString реализацию, которая скрывает реализацию базового класса.

Замечание

Набор средств сообщества Windows предоставляет BoolToVisibilityConverter. Преобразователь сопоставляется true со значением перечисления и Visiblefalse позволяет привязать Collapsed свойство к логическому объекту без создания преобразователяVisibility. Чтобы использовать преобразователь, проект должен добавить пакет NuGet CommunityToolkit.WinUI.Converters .

Привязка функции в {x:Bind}

{x:Bind} позволяет последнему шагу в пути привязки быть функцией. Используйте эту функцию для выполнения преобразований или создания привязок, зависящих от нескольких свойств. Дополнительные сведения см. в разделе "Функции" в x:Bind.

Привязка элемента к элементу

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

<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />

Словари ресурсов с {x:Bind}

Расширение разметки {x:Bind} зависит от создания кода, поэтому для инициализации созданного кода требуется файл программной части, содержащий конструктор InitializeComponent , вызывающий (инициализировать созданный код). Чтобы повторно использовать словарь ресурсов, создайте объект типа (так, чтобы InitializeComponent вызывался), вместо ссылки на его имя файла. Ниже приведен пример того, что делать, если у вас есть существующий словарь ресурсов и вы хотите использовать {x:Bind} его.

<!-- TemplatesResourceDictionary.xaml -->
<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>
// TemplatesResourceDictionary.xaml.cs
using Microsoft.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}
<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Window.Resources>
        <ResourceDictionary>
            .... 
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
</Window>

Сочетание {x:Bind} и {Binding} в повторно используемый стиль

В предыдущем примере показано, как использовать {x:Bind} в DataTemplates. Вы также можете создавать многократно используемые стили, которые объединяют расширения разметки {x:Bind} и {Binding}. Это сочетание полезно, если требуется привязать некоторые свойства к известным значениям во время компиляции с помощью {x:Bind} и другие свойства к значениям DataContext во время выполнения с помощью {Binding}.

В следующем примере показано, как создать повторно используемый стиль Button, который использует оба подхода к привязке:

TemplatesResourceDictionary.xaml

<!-- TemplatesResourceDictionary.xaml -->
<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <!-- DataTemplate using x:Bind -->
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
    
    <!-- Style that mixes x:Bind and Binding -->
    <Style x:Key="CustomButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="{Binding ButtonBackgroundBrush}"/>
        <Setter Property="Foreground" Value="{Binding ButtonForegroundBrush}"/>
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="Margin" Value="4"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="RootBorder"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="4">
                        <StackPanel Orientation="Horizontal" 
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                            <!-- x:Bind to a static property or page-level property -->
                            <Ellipse Width="8" Height="8" 
                                     Fill="{x:Bind DefaultIndicatorBrush}" 
                                     Margin="0,0,8,0"/>
                            <!-- Binding to DataContext -->
                            <ContentPresenter x:Name="ContentPresenter"
                                              Content="{TemplateBinding Content}"
                                              Foreground="{TemplateBinding Foreground}"
                                              FontSize="{TemplateBinding FontSize}"/>
                        </StackPanel>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <!-- Binding to DataContext for hover color -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{Binding ButtonHoverBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <VisualState.Setters>
                                        <!-- x:Bind to a compile-time known resource -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{x:Bind DefaultPressedBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.cs

// TemplatesResourceDictionary.xaml.cs
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
        
        // Properties for x:Bind - these are compile-time bound
        public SolidColorBrush DefaultIndicatorBrush { get; } = 
            new SolidColorBrush(Colors.Green);
            
        public SolidColorBrush DefaultPressedBrush { get; } = 
            new SolidColorBrush(Colors.DarkGray);
    }
}

Использование в MainWindow.xaml с ViewModel, которое предоставляет значения среды выполнения:

<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <Grid.DataContext>
            <examplenamespace:ButtonThemeViewModel/>
        </Grid.DataContext>
        
        <StackPanel Margin="20">
            <!-- These buttons use the mixed binding style -->
            <Button Content="Save" Style="{StaticResource CustomButtonStyle}"/>
            <Button Content="Cancel" Style="{StaticResource CustomButtonStyle}"/>
        </StackPanel>
    </Grid>
</Window>

ButtonThemeViewModel.cs (DataContext, предоставляющий значения привязки среды выполнения):

using System.ComponentModel;
using Microsoft.UI;
using Microsoft.UI.Xaml.Media;

namespace ExampleNamespace
{
    public class ButtonThemeViewModel : INotifyPropertyChanged
    {
        private SolidColorBrush _buttonBackgroundBrush = new SolidColorBrush(Colors.LightBlue);
        private SolidColorBrush _buttonForegroundBrush = new SolidColorBrush(Colors.DarkBlue);
        private SolidColorBrush _buttonHoverBrush = new SolidColorBrush(Colors.LightCyan);

        public SolidColorBrush ButtonBackgroundBrush
        {
            get => _buttonBackgroundBrush;
            set
            {
                _buttonBackgroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonBackgroundBrush)));
            }
        }

        public SolidColorBrush ButtonForegroundBrush
        {
            get => _buttonForegroundBrush;
            set
            {
                _buttonForegroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonForegroundBrush)));
            }
        }

        public SolidColorBrush ButtonHoverBrush
        {
            get => _buttonHoverBrush;
            set
            {
                _buttonHoverBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonHoverBrush)));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

В этом примере:

  • {Binding} используется для свойств, зависящих от DataContext (ButtonBackgroundBrush, ButtonForegroundBrush, ButtonHoverBrush)
  • {x:Bind} используется для свойств, известных во время компиляции и принадлежащих самому ResourceDictionary (DefaultIndicatorBrush, DefaultPressedBrush)
  • Стиль можно использовать повторно, и его можно применить к любой кнопке
  • Их можно использовать с помощью DataContext, используя преимущества производительности статических {x:Bind} элементов.

Привязка событий и ICommand

{x:Bind} поддерживает функцию, называемую привязкой событий. С помощью этой функции можно указать обработчик события с помощью привязки. Эта функция является дополнительным вариантом обработки событий, в дополнение к обработке событий методом в файле code-behind. Предположим, что в вашем MainWindow классе есть ListViewDoubleTapped обработчик событий.

public sealed partial class MainWindow : Window
{
    ...
    public void ListViewDoubleTapped()
    {
        // Handle double-tapped logic
    }
}

Вы можете привязать событие DoubleTapped ListView к методу в MainWindow , как показано ниже.

<ListView DoubleTapped="{x:Bind ListViewDoubleTapped}" />

Вы не можете использовать перегруженные методы для обработки события с помощью этого метода. Кроме того, если метод, обрабатывающий событие, имеет параметры, все из них должны быть назначены из типов всех параметров события соответственно. В этом случае ListViewDoubleTapped не перегружен и не имеет параметров (но он по-прежнему будет допустимым, даже если он принял два object параметра).

Метод привязки событий похож на реализацию и использование команд. Команда — это свойство, которое возвращает объект, реализующий интерфейс ICommand . Как {x:Bind}, так и {Binding} работают с командами. Так что вам не нужно реализовать шаблон команды несколько раз, можно использовать DelegateCommand вспомогательный класс, который вы найдете в примере UWP QuizGame (в папке Common).

Привязка к коллекции папок или файлов

API-интерфейсы в пространстве имен Windows.Storage можно использовать для получения данных папок и файлов в упакованных приложениях пакета SDK для приложений windows. Однако различные GetFilesAsync, GetFoldersAsync и GetItemsAsync методы не возвращают значения, которые подходят для привязки к элементам управления списками. Вместо этого необходимо привязать к возвращаемым значениям методов GetVirtualizedFilesVector, GetVirtualizedFoldersVector и GetVirtualizedItemsVector класса FileInformationFactory . В следующем примере кода из примера StorageDataSource и GetVirtualizedFilesVector UWP показан типичный шаблон использования. Не забудьте объявить функцию picturesLibrary в манифесте пакета приложения и убедиться, что в папке библиотеки изображений есть изображения.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var library = Windows.Storage.KnownFolders.PicturesLibrary;
    var queryOptions = new Windows.Storage.Search.QueryOptions();
    queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
    queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;

    var fileQuery = library.CreateFileQueryWithOptions(queryOptions);

    var fif = new Windows.Storage.BulkAccess.FileInformationFactory(
        fileQuery,
        Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
        190,
        Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
        false
        );

    var dataSource = fif.GetVirtualizedFilesVector();
    this.PicturesListView.ItemsSource = dataSource;
}

Обычно этот подход используется для создания представления сведений о файлах и папках только для чтения. Можно создать двусторонние привязки к свойствам файла и папки, например, чтобы пользователи могли оценить песню в музыкальном представлении. Однако любые изменения не сохраняются до вызова соответствующего SavePropertiesAsync метода (например, MusicProperties.SavePropertiesAsync). Если элемент теряет фокус, необходимо зафиксировать изменения, так как это действие активирует сброс выделения.

Обратите внимание, что двусторонняя привязка с помощью этого метода работает только с индексированных расположений, таких как Музыка. Можно определить, индексируется ли расположение, вызвав метод FolderInformation.GetIndexedStateAsync .

Обратите внимание также, что виртуализированный вектор может возвращать null некоторые элементы перед заполнением их значения. Например, перед null использованием значения SelectedItem элемента управления списком, привязанного к виртуализированному вектору, или использовать SelectedIndex вместо этого.

Привязка к данным, сгруппированных по ключу

Если вы берёте плоскую коллекцию элементов (например, книги, представленные классом BookSku) и группируете элементы, используя общее свойство (например, свойство BookSku.AuthorName) в качестве ключа, это называется сгруппированными данными. При группировке данных она больше не является плоской коллекцией. Сгруппированные данные — это коллекция объектов группы, где каждый объект группы имеет:

  • ключ и
  • коллекция элементов, свойство которых соответствует указанному ключу.

Чтобы повторить пример книг, результат группировки книг по имени автора приводит к коллекции групп имен автора, где каждая группа имеет:

  • ключ, который является именем автора, и
  • коллекция BookSku объектов, свойство которых AuthorName соответствует ключу группы.

Как правило, для отображения коллекции привязывается элемент управления ItemsSource элемента управления (например , ListView или GridView) непосредственно к свойству, возвращающего коллекцию. Если это плоская коллекция элементов, вам не нужно ничего специального. Но если это коллекция объектов группы (как и при привязке к группируемым данным), то вам нужны службы промежуточного объекта с именем CollectionViewSource , который находится между элементом управления элементами и источником привязки. Вы привязываете CollectionViewSource свойство, возвращающее сгруппированные данные, и привязываете элемент управления items к элементу CollectionViewSourceуправления . Дополнительное добавление CollectionViewSource значения заключается в том, что он отслеживает текущий элемент, поэтому вы можете сохранить несколько элементов управления в синхронизации, привязав их ко всем одинаковым CollectionViewSource. Вы также можете получить доступ к текущему элементу программным способом с помощью свойства ICollectionView.CurrentItem объекта, возвращаемого свойством CollectionViewSource.View .

Чтобы активировать объект группировки объекта CollectionViewSource, задайте для IsSourceGrouped значение true. Необходимо ли также задать свойство ItemsPath , зависит от того, как создавать объекты группы. Существует два способа создания объекта группы: шаблона is-a-group и шаблона has-a-group. В шаблоне "is-a-group" объект группы является производным от типа коллекции (например, List<T>поэтому объект группы фактически является группой элементов. При использовании этого шаблона не требуется задавать ItemsPath. В шаблоне "has-a-group" объект группы имеет одно или несколько свойств типа коллекции (например List<T>), поэтому группа имеет группу элементов в виде свойства (или несколько групп элементов в виде нескольких свойств). В этом шаблоне необходимо задать ItemsPath имя свойства, содержащего группу элементов.

В следующем примере показан шаблон "has-a-group". Класс окна имеет свойство DataContext, которое возвращает экземпляр модели представления. CollectionViewSource привязывается к Authors свойству модели представления (Authorsявляется коллекцией объектов группы), а также указывает, что это Author.BookSkus свойство, содержащее сгруппированные элементы. Наконец, GridView привязан к CollectionViewSourceобъекту и имеет свой стиль группы, чтобы он смог отобразить элементы в группах.

<Window.Resources>
    <CollectionViewSource
    x:Name="AuthorHasACollectionOfBookSku"
    Source="{x:Bind ViewModel.Authors}"
    IsSourceGrouped="true"
    ItemsPath="BookSkus"/>
</Window.Resources>
...
<GridView
ItemsSource="{x:Bind AuthorHasACollectionOfBookSku}" ...>
    <GridView.GroupStyle>
        <GroupStyle
            HeaderTemplate="{StaticResource AuthorGroupHeaderTemplateWide}" ... />
    </GridView.GroupStyle>
</GridView>

Вы можете реализовать шаблон "is-a-group" одним из двух способов. Одним из способов является создание собственного класса группы. Наследуйте класс ( List<T> где T является типом элементов). Например: public class Author : List<BookSku>. Второй способ — использовать выражение LINQ для динамического создания объектов группы (и класса группы) из таких значений свойств элементов BookSku . Такой подход — обслуживание только плоского списка элементов и группирование их вместе на лету — обычно это приложение, которое обращается к данным из облачной службы. Вы получаете гибкость для группирования книг по автору или по жанру (например), не нуждаясь в специальных классах группы, таких как автор и жанр.

В следующем примере показан шаблон "is-a-group" с помощью LINQ. На этот раз мы группируем книги по жанру, отображаемым с именем жанра в заголовках группы. Это группирование указывается путём пути свойства Key в ссылке на значение группы Key.

using System.Linq;
...
private IOrderedEnumerable<IGrouping<string, BookSku>> genres;

public IOrderedEnumerable<IGrouping<string, BookSku>> Genres
{
    get
    {
        if (genres == null)
        {
            genres = from book in bookSkus
                     group book by book.genre into grp
                     orderby grp.Key
                     select grp;
        }
        return genres;
    }
}

Помните, что при использовании {x:Bind} с шаблонами данных необходимо указать тип, к которому выполняется привязка, установив значение атрибута x:DataType. Если тип является универсальным, вы не можете выразить это в разметке, поэтому вам следует использовать {Binding} в шаблоне заголовка стиля группы.

    <Grid.Resources>
        <CollectionViewSource x:Name="GenreIsACollectionOfBookSku"
        Source="{x:Bind Genres}"
        IsSourceGrouped="true"/>
    </Grid.Resources>
    <GridView ItemsSource="{x:Bind GenreIsACollectionOfBookSku}">
        <GridView.ItemTemplate x:DataType="local:BookTemplate">
            <DataTemplate>
                <TextBlock Text="{x:Bind Title}"/>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

Элемент управления SemanticZoom — отличный способ просмотра и навигации пользователей сгруппированных данных. Пример приложения UWP Bookstore2 иллюстрирует использование SemanticZoomприложения . В этом приложении можно просмотреть список книг, сгруппированных по автору (увеличенное представление) или просмотреть список переходов авторов (увеличенное представление). Список переходов обеспечивает гораздо более быструю навигацию, чем прокрутка по списку книг. Масштабированные и увеличенные представления фактически ListViewGridView или элементы управления привязаны к одному и тому же CollectionViewSource.

Иллюстрация семантики

При привязке к иерархическим данным, таким как подкатегории в категориях, можно выбрать отображение иерархических уровней в пользовательском интерфейсе с рядом элементов управления. Выбор в одном элементе управления элементами определяет содержимое последующих элементов управления. Списки можно синхронизировать, привязав каждый список к собственному Объекту CollectionViewSource и привязав CollectionViewSource экземпляры к цепочке. Эта настройка называется представлением master/details (или list/details). Дополнительные сведения см. в разделе "Как привязать к иерархическим данным" и создать представление master/details.

Диагностика и отладка проблем привязки данных

Разметка привязки содержит имена свойств (и для C#, иногда поля и методы). Поэтому при переименовании свойства также необходимо изменить любую привязку, которая ссылается на нее. Если вы забыли это сделать, создайте ошибку привязки данных, и приложение либо не компилирует, либо не выполняется правильно.

Объекты привязки, создаваемые {x:Bind} и {Binding} , в значительной степени эквивалентны функционально. Но {x:Bind} имеет сведения о типе источника привязки, и он создает исходный код во время компиляции. С помощью {x:Bind} вы обнаруживаете проблемы так же, как и с остальным вашим кодом. Это обнаружение включает проверку ваших выражений привязки на этапе компиляции и отладку путем установки точек останова в исходном коде, созданном как частичный класс для вашей страницы. Эти классы можно найти в файлах в obj папке с такими именами, как (для C#). <view name>.g.cs Если у вас возникли проблемы с привязкой, включите опцию Остановиться на необработанных исключениях в отладчике Microsoft Visual Studio. Отладчик прерывает выполнение в этом моменте, и вы можете отладить то, что пошло не так. Код, созданный {x:Bind} по одному шаблону для каждой части графа исходных узлов привязки, и вы можете использовать сведения в окне стека вызовов , чтобы определить последовательность вызовов, которые привели к проблеме.

{Binding} не имеет сведений о типе источника привязки. Но при запуске приложения с присоединенным отладчиком все ошибки привязки отображаются в окнах вывода и привязок XAML в Visual Studio. Дополнительные сведения об ошибках отладки привязок в Visual Studio см. в разделе диагностики привязки данных XAML.

Создание привязок в коде

Замечание

Этот раздел применяется только к {Binding}, так как в коде нельзя создавать привязки {x:Bind} . Однако вы можете добиться некоторых из тех же самых преимуществ {x:Bind} с помощью DependencyObject.RegisterPropertyChangedCallback, что позволяет вам регистрировать уведомления об изменениях в любом свойстве зависимости.

Вы также можете подключить элементы пользовательского интерфейса к данным с помощью процедурного кода вместо XAML. Для этого создайте объект Binding, задайте соответствующие свойства, а затем вызовите FrameworkElement.SetBinding или BindingOperations.SetBinding.SetBinding. Создание привязок программным способом полезно при выборе значений свойств привязки во время выполнения или совместного использования одной привязки между несколькими элементами управления. Однако вы не можете изменить значения свойств привязки после вызова SetBinding.

В следующем примере показано, как реализовать привязку в коде.

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
var textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;

// Create the binding and associate it with the text box.
var binding = new Binding { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);

Сравнение функций {x:Bind} и {Binding}

Функция {x:Bind} и {Binding} Примечания.
Путь — это свойство по умолчанию {x:Bind a.b.c}
-
{Binding a.b.c}
Свойство Path {x:Bind Path=a.b.c}
-
{Binding Path=a.b.c}
x:Bind По Pathумолчанию корень находится в окне, а не DataContext.
Indexer {x:Bind Groups[2].Title}
-
{Binding Groups[2].Title}
Привязывается к указанному элементу в коллекции. Поддерживаются только целые индексы.
Присоединенные свойства {x:Bind Button22.(Grid.Row)}
-
{Binding Button22.(Grid.Row)}
Присоединенные свойства задаются с помощью скобок. Если свойство не объявлено в пространстве имен XAML, префиксируйте его с пространством имен XML, которое должно быть сопоставлено с пространством имен кода в начале документа.
Литьё {x:Bind groups[0].(data:SampleDataGroup.Title)}
-
Не требуется {Binding}.
Приведения задаются с помощью круглых скобок. Если свойство не объявлено в пространстве имен XAML, префиксируйте его с пространством имен XML, которое должно быть сопоставлено с пространством имен кода в начале документа.
Преобразователь {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}}
Объявите преобразователи в корне окна, элемента управления, ResourceDictionary или в App.xaml.
КонвертерПараметр, КонвертерЯзык {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
Объявите преобразователи в корне окна, элемента управления, ResourceDictionary или App.xaml.
TargetNullValue {x:Bind Name, TargetNullValue=0}
-
{Binding Name, TargetNullValue=0}
Используется, когда конечная часть выражения привязки имеет значение NULL. Используйте одинарные кавычки для строкового значения.
Резервное значение {x:Bind Name, FallbackValue='empty'}
-
{Binding Name, FallbackValue='empty'}
Используется, если любая часть пути для привязки (за исключением конечной) имеет значение NULL.
ElementName {x:Bind slider1.Value}
-
{Binding Value, ElementName=slider1}
При {x:Bind} вы привязываетесь к полю, а Path по умолчанию привязан к окну, поэтому вы можете получить доступ к любому именованному элементу через его поле.
ИсточникОтносительный: Self <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
-
<Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
Присвойите {x:Bind}элементу имя и используйте его имя в Path.
RelativeSource: TemplatedParent Не требуется {x:Bind}
-
{Binding <path>, RelativeSource={RelativeSource TemplatedParent}}
{x:Bind} TargetType С параметром ControlTemplateon указывает привязку к родительскому элементу шаблона. Для {Binding}большинства используемых шаблонов можно использовать обычную привязку шаблонов в шаблонах элементов управления. Но используйте TemplatedParent , где необходимо использовать преобразователь или двусторонняя привязка.
Исходный материал Не требуется {x:Bind}
-
<ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/>
Для {x:Bind} можно напрямую использовать именованный элемент, воспользоваться свойством или статическим путем.
Mode {x:Bind Name, Mode=OneWay}
-
{Binding Name, Mode=TwoWay}
Mode может быть OneTime, OneWayили TwoWay. {x:Bind} OneTimeпо умолчанию — {Binding} по умолчаниюOneWay.
UpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
-
{Binding UpdateSourceTrigger=PropertyChanged}
UpdateSourceTrigger может быть Default, LostFocusили PropertyChanged. {x:Bind} не поддерживает UpdateSourceTrigger=Explicit. {x:Bind} использует PropertyChanged поведение для всех случаев, за исключением TextBox.Textслучаев, когда оно использует LostFocus поведение.

См. также