Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
В этой статье описываются функции привязки данных WinUI 3 с помощью API в пространстве имен Microsoft.UI.Xaml.Data.
Замечание
В этом разделе подробно описаны функции привязки данных. Краткое практическое введение см. в обзоре привязки данных.
Важные API
Введение
Привязка данных — это метод, позволяющий пользовательскому интерфейсу приложения эффективно отображать и синхронизировать данные. Разделив проблемы с данными от проблем пользовательского интерфейса, она упрощает проектирование приложения, повышает удобочитаемость и повышает удобство обслуживания.
Привязка данных позволяет просто отображать значения из источника данных при первом отображении пользовательского интерфейса, но не реагировать на изменения этих значений. Этот режим привязки называется однократным, и он хорошо подходит для значения, которое не изменяется во время выполнения. Кроме того, можно выбрать "наблюдать" значения и обновлять пользовательский интерфейс при их изменении. Этот режим называется односторонним, и он хорошо подходит для данных только для чтения. В конечном счете можно выбрать как наблюдать, так и обновлять, чтобы изменения, внесенные пользователем в значения в пользовательском интерфейсе, автоматически отправляются обратно в источник данных. Этот режим называется двусторонним, и он хорошо подходит для данных чтения и записи. Ниже приведены некоторые примеры.
- Вы можете использовать одноразовый режим для привязки изображения к фотографии текущего пользователя.
- Вы можете использовать односторонний режим для привязки ListView к коллекции новостей в режиме реального времени, сгруппированных по разделу газеты.
- Вы можете использовать двусторонний режим для привязки TextBox к имени клиента в форме.
Независимо от режима, существует два типа привязки, и обычно вы объявляете оба в разметке пользовательского интерфейса. Вы можете использовать расширение разметки {x:Bind} или расширение разметки {Binding}. Вы даже можете использовать смесь двух в одном приложении, даже в одном элементе пользовательского интерфейса.
{x:Bind} является новым в UWP для Windows 10 и обеспечивает лучшую производительность. Все сведения, описанные в этом разделе, применяются к обоим типам привязки, если мы явно не говорим в противном случае.
Примеры приложений UWP, демонстрирующие {x:Bind}
- {x:Bind} sample.
- QuizGame.
- пример XAML UI Basics.
Примеры приложений UWP, демонстрирующие {Binding}
- Скачайте приложение UWP Bookstore1.
- Скачайте приложение Bookstore2.
Каждая привязка включает в себя эти части
- Источник привязки. Этот источник предоставляет данные для привязки. Это может быть экземпляр любого класса с элементами, значения которых необходимо отобразить в пользовательском интерфейсе.
- Целевой объект привязки. Этот целевой элемент — свойство зависимости элемента 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 доступен с Windows App SDK. Без этого атрибута необходимо реализовать интерфейсы 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 доступен с Windows App SDK. Без этого атрибута необходимо реализовать интерфейсы 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 элемента пользовательского интерфейса, на котором объявлена привязка. Этот параметр по умолчанию можно переопределить, установив Source, RelativeSource или 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 со значением перечисления Visible, а false с 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. Предположим, что в вашем ListViewDoubleTapped классе есть MainWindow обработчик событий.
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, который вы найдете в QuizGame UWP (в папке Common).
Привязка к коллекции папок или файлов
API можно использовать в пространстве имен Windows.Storage для получения данных папок и файлов в упакованных приложениях Windows App SDK. Однако различные 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 элемента управления списком, привязанного к виртуализированному вектору, проверьте , или используйте 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. В этом приложении можно просмотреть список книг, сгруппированных по автору (вид вблизи) или отдалить, чтобы увидеть список авторов (вид издалека). Список переходов обеспечивает гораздо более быструю навигацию, чем прокрутка по списку книг. Увеличенное и уменьшенное представления фактически представляют собой элементы управления ListView или GridView, связанные с одним и тем же CollectionViewSource.
При привязке к иерархическим данным, таким как подкатегории в категориях, можно выбрать отображение иерархических уровней в пользовательском интерфейсе с рядом элементов управления. Выбор элемента в одном элементе управления списком определяет содержимое последующих элементов управления списками. Списки можно синхронизировать, привязав каждый список к собственному Объекту CollectionViewSource и привязав CollectionViewSource экземпляры к цепочке. Эта настройка называется представлением master/details (или list/details). Дополнительные сведения см. в разделе «Как привязать к иерархическим данным и создать основное/дополнительное представление».
Диагностика и отладка проблем привязки данных
Разметка привязки содержит имена свойств (а для C# — иногда и поля, и методы). Поэтому при переименовании свойства также необходимо изменить любую привязку, которая ссылается на нее. Если вы забыли это сделать, вы создаёте ошибку привязки данных, и ваше приложение либо не компилируется, либо работает неправильно.
Объекты привязки, создаваемые {x:Bind} и {Binding} , в значительной степени эквивалентны функционально. Но {x:Bind} имеет сведения о типе источника привязки, и он создает исходный код во время компиляции. С помощью {x:Bind} вы обнаруживаете проблемы так же, как и с остальным вашим кодом. Это обнаружение включает проверку ваших выражений привязки на этапе компиляции и отладку путем установки точек останова в исходном коде, созданном как частичный класс для вашей страницы. Эти классы можно найти в файлах в obj папке с такими именами, как (для C#). <view name>.g.cs Если у вас возникла проблема с привязкой, включите Break On Unhandled Exceptions в отладчике Microsoft Visual Studio. Отладчик прерывает выполнение в этом моменте, и вы можете отладить то, что пошло не так. Код, создаваемый {x:Bind}, следует одинаковому шаблону для каждой части графа узлов источника привязки, и вы можете использовать информацию в окне стека вызовов, чтобы определить последовательность вызовов, которые привели к проблеме.
{Binding} не имеет сведений о типе источника привязки. Но при запуске приложения с подключенным отладчиком все ошибки привязки отображаются в окнах Output и XAML Binding Failures в Visual Studio. Дополнительные сведения об отладке ошибок привязки в Visual Studio см. в разделе диагностика привязки данных XAML.
Создание привязок в коде
Замечание
Этот раздел применяется только к {Binding}, так как в коде нельзя создавать привязки {x:Bind} . Однако вы можете добиться некоторых из тех же самых преимуществ {x:Bind} с помощью DependencyObject.RegisterPropertyChangedCallback, что позволяет вам регистрировать уведомления об изменениях в любом свойстве зависимости.
Вы также можете подключить элементы пользовательского интерфейса к данным с помощью процедурного кода вместо XAML. Чтобы это сделать, создайте новый объект Binding, задайте соответствующие свойства, а затем вызовите FrameworkElement.SetBinding или BindingOperations.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. |
| ОтносительныйИсточник: ШаблонныйРодитель | Не требуется для {x:Bind}- {Binding <path>, RelativeSource={RelativeSource TemplatedParent}} |
{x:Bind}
TargetType на ControlTemplate указывает привязку к родительскому элементу шаблона. Для {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 поведение. |
См. также
Windows developer