Привязываемые свойства

Привязываемые свойства пользовательского интерфейса приложений .NET (.NET MAUI) расширяют функциональные возможности свойств среды CLR , создав свойство с BindableProperty типом вместо поля. Цель привязываемых свойств — предоставить систему свойств, которая поддерживает привязку данных, стили, шаблоны и значения, заданные через отношения родительского-дочернего объекта. Кроме того, привязываемые свойства могут предоставлять значения по умолчанию, проверку значений свойств и обратные вызовы, отслеживающие изменения свойств.

В приложениях .NET MAUI свойства должны быть реализованы как привязываемые свойства для поддержки одной или нескольких следующих функций:

  • Действует как допустимое целевое свойство для привязки данных. Дополнительные сведения о целевых свойствах см. в разделе "Базовые привязки".
  • Задание свойства с помощью стиля.
  • Предоставление значения свойства по умолчанию, отличное от значения по умолчанию для типа свойства.
  • Проверка значения свойства.
  • Мониторинг изменений свойств.

Примеры привязываемых свойств .NET MAUI: Label.Textи Button.BorderRadiusStackLayout.Orientation. Каждое привязываемое свойство имеет соответствующее public static readonly поле типа BindableProperty , которое предоставляется в одном классе и является идентификатором привязываемого свойства. Например, соответствующий Label.TextPropertyидентификатор привязываемого свойства для Label.Text свойства.

Создание привязываемого свойства

Процесс создания привязываемого свойства выглядит следующим образом:

  1. BindableProperty Создайте экземпляр с одной из BindableProperty.Create перегрузок метода.
  2. Определите методы доступа к свойствам для экземпляра BindableProperty .

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

Создание свойства

Чтобы создать BindableProperty экземпляр, содержащий класс должен быть производным от BindableObject класса. BindableObject Однако класс имеет высокий уровень в иерархии классов, поэтому большинство классов, используемых для функций пользовательского интерфейса, поддерживают привязываемые свойства.

Привязываемое свойство можно создать путем объявления public static readonly свойства типа BindableProperty. Привязываемое свойство должно быть задано возвращаемым значением одной из BindableProperty.Create перегрузок метода. Объявление должно находиться в теле производного класса, но вне определений BindableObject элементов.

Как минимум, при создании BindablePropertyидентификатора необходимо указать вместе со следующими параметрами:

  • Имя BindableProperty.
  • Тип свойства.
  • Тип объекта владения.
  • Значение по умолчанию для свойства. Это гарантирует, что свойство всегда возвращает определенное значение по умолчанию, если оно не задано, и оно может отличаться от значения по умолчанию для типа свойства. Значение по умолчанию будет восстановлено при ClearValue вызове метода в привязываемом свойстве.

Внимание

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

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

public static readonly BindableProperty IsExpandedProperty =
  BindableProperty.Create ("IsExpanded", typeof(bool), typeof(Expander), false);

При этом создается BindableProperty экземпляр с именем IsExpandedProperty, типом bool. Свойство принадлежит классу Expander и имеет значение falseпо умолчанию.

При необходимости при создании экземпляра BindableProperty можно указать следующие параметры:

  • Режим привязки. Используется для указания направления, в котором будут распространяться изменения значения свойства. В режиме привязки по умолчанию изменения будут распространяться из источника на целевой объект. Дополнительные сведения см. в разделе "Базовые привязки".
  • Делегат проверки, который будет вызываться при установке значения свойства. Дополнительные сведения см. в статье Обратные вызовы проверки.
  • Измененный делегат свойства, который будет вызываться при изменении значения свойства. Дополнительные сведения см. в разделе "Обнаружение изменений свойств".
  • Делегат изменения свойства, который будет вызываться при изменении значения свойства. Этот делегат имеет ту же подпись, что и измененный делегат свойства.
  • Делегат принудительного значения, который будет вызываться при изменении значения свойства. Дополнительные сведения см. в разделе обратных вызовов значения Coerce.
  • Значение Func свойства по умолчанию используется для инициализации значения свойства по умолчанию. Дополнительные сведения см. в разделе "Создание значения по умолчанию" с помощью Func.

Создание методов доступа

Методы доступа к свойствам необходимы для использования синтаксиса свойств для доступа к привязываемому свойству. Метод Get доступа должен возвращать значение, содержащееся в соответствующем привязываемом свойстве. Это можно сделать путем вызова GetValue метода, передачи идентификатора привязываемого свойства, для которого требуется получить значение, а затем приведения результата к требуемому типу. Метод Set доступа должен задать значение соответствующего привязываемого свойства. Это можно добиться, вызвав SetValue метод, передав идентификатор привязываемого свойства, для которого необходимо задать значение, и значение, которое необходимо задать.

В следующем примере кода показаны методы доступа для привязываемого IsExpanded свойства:

public bool IsExpanded
{
    get => (bool)GetValue(IsExpandedProperty);
    set => SetValue(IsExpandedProperty, value);
}

Использование привязываемого свойства

После создания привязываемого свойства его можно использовать из XAML или кода. В XAML это достигается путем объявления пространства имен с префиксом, с объявлением пространства имен, указывающим имя пространства имен CLR и необязательное имя сборки. Дополнительные сведения см. в разделе "Пространства имен XAML".

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

<ContentPage ... xmlns:local="clr-namespace:DataBindingDemos" ...>
  ...
</ContentPage>

Объявление пространства имен используется при задании привязываемого IsExpanded свойства, как показано в следующем примере кода XAML:

<Expander IsExpanded="true">
    ...
</Expander>

Эквивалентный код на языке C# показан в следующем примере:

Expander expander = new Expander
{
    IsExpanded = true
};

Расширенные сценарии

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

Обнаружение изменений свойств

Метод static обратного вызова с измененным свойством можно зарегистрировать с привязываемым свойством, указав propertyChanged параметр для BindableProperty.Create метода. Указанный метод обратного вызова вызывается при изменении значения привязываемого свойства.

В следующем примере кода показано, как IsExpanded привязываемое свойство регистрирует OnIsExpandedChanged метод в качестве метода обратного вызова с измененным свойством:

public static readonly BindableProperty IsExpandedProperty =
    BindableProperty.Create(nameof(IsExpanded), typeof(bool), typeof(Expander), false, propertyChanged: OnIsExpandedChanged);
...

static void OnIsExpandedChanged (BindableObject bindable, object oldValue, object newValue)
{
  // Property changed implementation goes here
}

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

Обратные вызовы проверки

Метод static обратного вызова проверки можно зарегистрировать с привязываемым свойством, указав validateValue параметр для BindableProperty.Create метода. Указанный метод обратного вызова будет вызываться при установке значения привязываемого свойства.

В следующем примере кода показано, как Angle привязываемое свойство регистрирует IsValidValue метод в качестве метода обратного вызова проверки:

public static readonly BindableProperty AngleProperty =
    BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, validateValue: IsValidValue);
...

static bool IsValidValue(BindableObject view, object value)
{
    double result;
    double.TryParse(value.ToString(), out result);
    return (result >= 0 && result <= 360);
}

Обратные вызовы проверки предоставляются со значением и должны возвращаться true , если значение допустимо для свойства, в противном случае false. Исключение будет возникать, если возвращается falseобратный вызов проверки, который следует обрабатывать. Обычное использование метода обратного вызова проверки ограничивает значения целых чисел или двойных значений при установке привязываемого свойства. Например, метод проверка, IsValidValue что значение свойства находится double в диапазоне от 0 до 360.

Обратные вызовы со значением coerce

Метод static обратного вызова принудительного значения можно зарегистрировать с привязываемым свойством, указав coerceValue параметр для BindableProperty.Create метода. Указанный метод обратного вызова будет вызываться при изменении значения привязываемого свойства, чтобы можно было настроить новое значение перед применением.

Внимание

Помимо активации подсистемы привязываемых свойств, можно вызывать обратные вызовы coerce-value из кода. Тип BindableObject имеет CoerceValue метод, который можно вызвать для принудительной переоценки значения его BindableProperty аргумента, вызывая обратный вызов значения принудительная.

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

В следующем примере кода показано, как Angle привязываемое свойство регистрирует CoerceAngle метод в качестве метода обратного вызова со значением coerce:

public static readonly BindableProperty AngleProperty =
    BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty =
    BindableProperty.Create("MaximumAngle", typeof(double), typeof(MainPage), 360.0, propertyChanged: ForceCoerceValue);
...

static object CoerceAngle(BindableObject bindable, object value)
{
    MainPage page = bindable as MainPage;
    double input = (double)value;

    if (input > page.MaximumAngle)
    {
        input = page.MaximumAngle;
    }

    return input;
}

static void ForceCoerceValue(BindableObject bindable, object oldValue, object newValue)
{
    bindable.CoerceValue(AngleProperty);
}

Метод CoerceAngle проверка значение MaximumAngle свойства, а если Angle значение свойства больше, оно принудивает значение MaximumAngle к значению свойства. Кроме того, при MaximumAngle изменении свойства обратный вызов значения coerce вызывается для Angle свойства путем вызова CoerceValue метода.

Создание значения по умолчанию с помощью Func

Можно Func использовать для инициализации значения по умолчанию привязываемого свойства, как показано в следующем примере:

public static readonly BindableProperty DateProperty =
    BindableProperty.Create ("Date", typeof(DateTime), typeof(MyPage), default(DateTime), BindingMode.TwoWay, defaultValueCreator: bindable => DateTime.Today);

Параметр defaultValueCreator имеет значение, Func возвращающее текущую DateTime дату.