Расширение разметки x:Bind

Примечание Общие сведения об использовании привязки данных в приложении с помощью {x:Bind} (а также подробное сравнение между {x:Bind} и {Binding}) см. в разделе Привязка данных.

Расширение разметки {x:Bind} — новая функция для Windows 10 — является альтернативой для {Binding}. {x:Bind} выполняется за меньшее время и меньше памяти, чем {Binding} , и поддерживает лучшую отладку.

Во время компиляции XAML {x:Bind} преобразуется в код, который получает значения из свойства в источнике данных и устанавливает его для свойства, определенного в разметке. Объект привязки можно дополнительно настроить таким образом, чтобы он регистрировал изменения значений свойства источника данных и сам обновлялся на основании этих данных (Mode="OneWay"). Кроме того, его можно настроить, чтобы он отправлял изменения собственного значения назад к свойству источника (Mode="TwoWay").

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

Совет

{x:Bind} имеет режим по умолчанию OneTime, в отличие от {Binding} с режимом по умолчанию OneWay. Он был выбран в целях повышения производительности, поскольку при использовании OneWay создается больший объем кода для подключения и обнаружения изменений. Можно явно задать режим, чтобы использовать привязку OneWay или TwoWay. x:DefaultBindMode можно также использовать, чтобы изменить режим по умолчанию для {x:Bind} для определенного сегмента дерева разметки. Выбранный режим применяет любые выражения {x:Bind} к этому элементу и его дочерним элементам, которые явным образом не задают режим в качестве части привязки.

Примеры приложений с расширением разметки {x:Bind}

Использование атрибутов XAML

<object property="{x:Bind}" .../>
-or-
<object property="{x:Bind propertyPath}" .../>
-or-
<object property="{x:Bind bindingProperties}" .../>
-or-
<object property="{x:Bind propertyPath, bindingProperties}" .../>
-or-
<object property="{x:Bind pathToFunction.functionName(functionParameter1, functionParameter2, ...), bindingProperties}" .../>
Термин Описание
Propertypath Строка, указывающая путь свойства для привязки. Подробную информацию см. в разделе Путь свойства ниже.
bindingProperties
propName=value[, propName=value]* Одна или несколько привязок свойств, указанных с помощью синтаксиса пары "имя/значение".
propName Имя строки свойства для установки на объекте привязки. Например, Converter.
value Значение, которое следует задать для свойства. Синтаксис аргумента зависит от задаваемого свойства. Ниже приведен пример использованиязначенияpropName=, где значение само является расширением разметки: Converter={StaticResource myConverterClass}. Дополнительную информацию см. в разделе Свойства, которые можно задать с помощью расширения разметки {x:Bind} ниже.

Примеры

<Page x:Class="QuizGame.View.HostView" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

В этом примере кода XAML используется {x:Bind} со свойством ListView.ItemTemplate. Обратите внимание на объявление значения x:DataType.

  <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>

Путь к свойству

PropertyPath задает значение Path для выражения {x:Bind}. Path — путь к свойству, в котором определено значение свойства, подсвойства, поля или метода, к которому выполняется привязка (источник). Можно упомянуть точное имя свойства Path: {x:Bind Path=...}. Или его можно не указывать: {x:Bind ...}.

Разрешение пути свойства

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

Например, на странице: Text="{x:Bind Employee.FirstName}" будет искать участника Employee на странице, а затем участника FirstName в объекте, возвращенном участником Employee. Если бы элемент управления элементами привязывался к свойству, содержащему подчиненных сотрудников, то путем свойства мог бы быть Employee.Dependents, а шаблон элемента управления элементами, отобразил бы элементы в Dependents.

В случае использования языков C++/CX {x:Bind} нельзя привязать к частным полям и свойствам в модели страницы или данных — вам потребуется открытое свойство для выполнения привязки. Контактную зону для привязки необходимо предоставлять в качестве классов/интерфейсов CX, чтобы можно было получить соответствующие метаданные. Атрибут [Bindable] не требуется.

При использовании x:Bind вам не нужно применять ElementName=xxx как часть выражения привязки. Вместо этого можно использовать имя элемента в качестве первой части пути для привязки, так как именованные элементы становятся полями на странице или в пользовательском элементе управления, представляющем корневой источник привязки.

Коллекции

Если источником данных выступает коллекция, то в пути свойства можно указывать элементы коллекции по их позиции или индексу. Например, "Teams[0]. Players", где литерал "[]" заключает в себя "0", запрашивающий первый элемент в коллекции с нулевой индексированием.

Чтобы воспользоваться индексатором, модели необходимо реализовать IList<T> или IVector<T> в типе свойства, которое подлежит индексации. (Обратите внимание, что IReadOnlyList<T> и IVectorView<T> не поддерживают синтаксис индексатора.) Если тип индексированного свойства поддерживает INotifyCollectionChanged или IObservableVector и привязка OneWay или TwoWay, оно будет регистрировать и прослушивать уведомления об изменениях в этих интерфейсах. Логика отслеживания изменений обновляется с учетом всех изменений коллекции, даже если эти изменения не влияют на конкретное индексированное значение. Это обусловлено тем, что логика ожидания передачи данных общая для всех экземпляров коллекции.

Если источником данных выступает словарь или карта, то в пути свойства можно указывать элементы коллекции по имени строки. Например <, TextBlock Text="{x:Bind Players['John Smith']}" /> будет искать элемент в словаре с именем "John Smith". Имя необходимо заключить в кавычки, которые могут быть как двойными, так и одинарными. Для экранирования кавычек в строках можно использовать символ карет (^). Обычно проще всего использовать альтернативные кавычки из тех, которые используются для атрибута XAML. (Обратите внимание, что IReadOnlyDictionary<T> и IMapView<T> не поддерживают синтаксис индексатора.)

Чтобы воспользоваться индексатором строки, модели необходимо реализовать IDictionary<string, T> or IMap<string, T> в типе свойства, которое подлежит индексации. Если тип индексированного свойства поддерживает IObservableMap, а привязка относится к типу OneWay или TwoWay, то она будет принимать и регистрировать уведомления об изменениях на этих интерфейсах. Логика отслеживания изменений обновляется с учетом всех изменений коллекции, даже если эти изменения не влияют на конкретное индексированное значение. Это обусловлено тем, что логика ожидания передачи данных общая для всех экземпляров коллекции.

Присоединенные свойства

Чтобы выполнить привязку к присоединенным свойствам, необходимо поместить класс и имя свойства в круглые скобки после точки. Например, Text="{x:Bind Button22.(Grid.Row)}". Если свойство не объявляется в пространстве имен Xaml, нужно установить для него префикс пространства имен xml, которое необходимо сопоставить с пространством имен кода в заголовке документа.

Приведение

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

В следующем случае obj является свойством объекта типа, но содержит текстовое поле, что позволяет использовать Text="{x:Bind ((TextBox)obj).Text}" или Text="{x:Bind obj.(TextBox.Text)}".

Поле groups3 в Text="{x:Bind ((data:SampleDataGroup)groups3[0]). Title}" — это словарь объектов, поэтому его необходимо привести к data:SampleDataGroup. Обратите внимание на то, как используется префикс пространства имен XML data: для сопоставления типа объектов с пространством имен кода, не являющимся частью пространства имен XAML по умолчанию.

Примечание. Синтаксис приведения в стиле C# является более гибким, чем синтаксис присоединенного свойства, и является рекомендуемой синтаксисой в будущем.

Безпутежное приведение

Средство синтаксического анализа собственных привязок не предоставляет ключевое слово для представления this в качестве параметра функции, но поддерживает беспутьное приведение (например, {x:Bind (x:String)}), которое можно использовать в качестве параметра функции. Таким образом, является допустимым способом выполнения того, {x:Bind MethodName((namespace:TypeOfThis))} что концептуально эквивалентно {x:Bind MethodName(this)}.

Пример

Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}"

<Page
    x:Class="AppSample.MainPage"
    ...
    xmlns:local="using:AppSample">

    <Grid>
        <ListView ItemsSource="{x:Bind Songs}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:SongItem">
                    <TextBlock
                        Margin="12"
                        FontSize="40"
                        Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
namespace AppSample
{
    public class SongItem
    {
        public string TrackName { get; private set; }
        public string ArtistName { get; private set; }

        public SongItem(string trackName, string artistName)
        {
            ArtistName = artistName;
            TrackName = trackName;
        }
    }

    public sealed partial class MainPage : Page
    {
        public List<SongItem> Songs { get; }
        public MainPage()
        {
            Songs = new List<SongItem>()
            {
                new SongItem("Track 1", "Artist 1"),
                new SongItem("Track 2", "Artist 2"),
                new SongItem("Track 3", "Artist 3")
            };

            this.InitializeComponent();
        }

        public static string GenerateSongTitle(SongItem song)
        {
            return $"{song.TrackName} - {song.ArtistName}";
        }
    }
}

Функции в путях привязки

Начиная с Windows 10 версии 1607 {x: Bind} поддерживает использование функции на конечном этапе шаге пути привязки. Это мощная функция привязки данных, которая позволяет использовать несколько сценариев в разметке. Дополнительные сведения см. в разделе Привязки функций .

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

Привязка события – это уникальная функция для компилированной привязки. Она позволяет определять обработчик для события с использованием привязки, а не применяется в качестве метода в коде программной части. Например, Click="{x:Bind rootFrame.GoForward}".

В случае работы с событиями метод не должен быть перегружен; он должен соответствовать таким условиям:

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

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

Дополнительную информацию о синтаксисе строк для пути свойства см. в разделе Синтаксис пути свойства, учитывая отличия {x:Bind}, описанные в данной статье.

Свойства, которые можно задать с помощью расширения разметки {x:Bind}

{x:Bind} демонстрируется с помощью замещающего синтаксиса bindingProperties, поскольку есть несколько свойств, доступных для чтения и записи, которые можно задавать в данном случае использования расширения разметки. Свойства можно задать в любом порядке с помощью парзначенийpropName= с разделителями-запятыми. Обратите внимание, что разрывы строк недопустимы в выражении привязки. Для некоторых свойств требуются типы, не предусматривающие преобразования; им необходимы их собственные расширения разметки, вложенные в {x:Bind}.

Эти свойства работают практически так же, как и свойства класса Binding.

Свойство Описание
Путь См. раздел Путь к свойству выше.
Конвертер Указывает объект преобразователя, вызываемый механизмом привязки. Преобразователь можно задать в коде XAML, но только в случае, если вы ссылаетесь на экземпляр объекта, присвоенный в ссылке на расширение разметки {StaticResource} этому объекту в словаре ресурсов.
ConverterLanguage Указывает язык и региональные параметры, используемые преобразователем. (Если задается свойство ConverterLanguage, также следует задать свойство Converter.) Язык и региональные параметры задаются как стандартный идентификатор. Подробнее: ConverterLanguage.
ConverterParameter Указывает параметр преобразователя, который можно использовать в логике преобразователя. (Если задается ConverterParameter, также следует задать свойство Converter.) Большая часть преобразователей использует простую логику для получения всей необходимой информации из переданного значения, и им не нужно значение ConverterParameter. Параметр ConverterParameter используется для более расширенных преобразователей, у которых больше одной логики и которым недостаточно информации, переданной в ConverterParameter. Вы также можете написать преобразователь, который использует нестроковые значения, но это используется редко. Подробнее см. в разделе "Примечания" статьи ConverterParameter.
FallbackValue Задает значение, которое отображается, когда не удается разрешить источник или путь.
Режим Указывает режим привязки как одну из этих строк: OneTime, OneWay или TwoWay. Значение по умолчанию — OneTime. Обратите внимание, что это поведение отличается от шаблона по умолчанию для привязки {Binding}, которая в большинстве случаев имеет значение OneWay.
TargetNullValue Задает значение, которое отображается, когда значение источника разрешается, но оно явно равно null.
BindBack Определяет функцию, используемую для обратного направления двусторонней привязки.
UpdateSourceTrigger Указывает, когда возвращать изменения в элементе управления модели в привязках TwoWay. Значение по умолчанию для всех свойств, кроме TextBox.Text, — PropertyChanged; TextBox.Text имеет значение LostFocus.

Примечание

Если вы преобразуете разметку {Binding} в {x:Bind}, следует учитывать различия между значениями по умолчанию для свойства Mode. x:DefaultBindMode можно использовать для изменения режима по умолчанию для x: Bind для конкретного сегмента дерева разметки. Выбранный режим будет применять любые выражения x:Bind к этому элементу и его дочерним элементам, которые явным образом не задают режим в качестве части привязки. OneTime отличается более высокой производительностью, чем OneWay, поскольку в результате использования OneWay создается больший объем кода для подключения и обнаружения изменений.

Комментарии

Поскольку {x:Bind} использует сформированный код, во время компиляции ему необходима информация о типе, чтобы воспользоваться всеми доступными преимуществами. Это означает, что, не зная заранее тип, вы не сможете выполнить привязку к свойствам. По этой причине невозможно использовать {x:Bind} со свойством DataContext, которое относится к типу Object и может во время выполнения изменяться.

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

Скомпилированные привязки зависят от создания кода. Если вы используете {x:Bind} в словаре ресурсов, тогда словарь ресурсов должен иметь класс кода программной части. Пример кода см. в разделе Словари ресурсов с привязкой {x:Bind}.

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

  • Update() — обновляет значения всех скомпилированных привязок. Все односторонние или двухсторонние привязки имеют прослушиватели для отслеживания изменений.
  • Initialize() — Если привязки еще не инициализированы, будет вызван метод Update() для инициализации привязок.
  • StopTracking() — отключает все прослушиватели, созданные для одно- и двухсторонних привязок. Прослушиватели можно инициализировать повторно с помощью метода Update().

Примечание

Начиная с Windows 10 версии 1607, платформа XAML предоставляет встроенный преобразователь Boolean в Visibility. Преобразователь сопоставляет значение true со значением перечисления Visible , а falseCollapsed , чтобы можно было привязать свойство Visibility к логическому объекту без создания преобразователя. Обратите внимание, что это не особенность привязки функций, а исключительно привязка свойств. Для использования встроенного преобразователя минимальная версия целевого пакета SDK вашего приложения должна быть 14393 или более поздней. Вы не сможете использовать преобразователь, если ваше приложение предназначено для более ранних версий Windows 10. Дополнительные сведения о целевых версиях см. в статье Адаптивный к версии код.

Совет. Если необходимо указать одну фигурную скобку для значения, например в Path или ConverterParameter, перед ней следует использовать обратную косую черту: \{. Также можно включить всю строку, содержащую скобки, которые нужно преобразовать, в дополнительный набор кавычек, например: ConverterParameter='{Mix}'.

Converter, ConverterLanguage и ConverterLanguage связаны с сценарием преобразования значения или типа из источника привязки в тип или значение, совместимые со свойством цели привязки. Более подробную информацию и примеры см. в разделе "Преобразования данных" статьи Подробно о привязке данных.

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