Общие сведения о присоединенных свойствах

Присоединенное свойство является концепцией языка XAML. Присоединенные свойства позволяют задавать дополнительные пары свойств или значений для объекта, но при этом они не является частью первоначального определения объекта. Присоединенные свойства обычно определяются как специализированная форма свойства зависимостей, у которого нет обычной оболочки в объектной модели типа владельца.

Предварительные требования

Данный текст предполагает, что вы знакомы с основной концепцией свойств зависимостей и прочли Общие сведения о свойствах зависимостей.

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

В XAML присоединенные свойства задаются с помощью синтаксиса AttachedPropertyProvider.PropertyName. Приведем пример установки свойства Canvas.Left в языке XAML.

<Canvas>
  <Button Canvas.Left="50">Hello</Button>
</Canvas>

Примечание

Мы просто используем Canvas.Left в качестве примера присоединенного свойства без полного объяснения причин его использования. Чтобы получить подробную информацию о назначении свойства Canvas.Left и о том, как Canvas обрабатывает представления его дочерних элементов, см. связанный раздел Canvas или Определение макетов с помощью XAML.

Зачем нужны присоединенные свойства?

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

Например, дочерние элементы могут использовать присоединенные свойства, чтобы передавать сведения своему родительскому элементу о том, как их необходимо представить в пользовательском интерфейсе. Именно так обстоит дело с присоединенным свойством Canvas.Left. Свойство Canvas.Left создается как присоединенное свойство, поскольку оно чаще устанавливается для элементов, входящих в состав элемента Canvas, чем для самого Canvas. Любые возможные дочерние элементы затем используют Canvas.Left и Canvas.Top для указания смещения макета внутри родительского контейнера макета Canvas. Присоединенные свойства позволяют использовать такой подход, не засоряя объектную модель базового элемента массой свойств, каждое из которых относится лишь к одному из многих возможных контейнеров макетов. Вместо этого многие из контейнеров макетов реализуют свой собственный набор присоединенных свойств.

Для реализации присоединенного свойства класс Canvas определяет статическое поле DependencyProperty с именем Canvas.LeftProperty. Затем Canvas предоставляет методы SetLeft и GetLeft в качестве открытых методов доступа для присоединенного свойства, чтобы сделать возможными как настройку XAML, так и доступ к значению во время выполнения. В языке XAML и системе свойств зависимостей данный набор API удовлетворяет шаблону, который подключает определенный синтаксис XAML для присоединенных свойств и сохраняет значение в хранилище свойства зависимостей.

Использование присоединенных свойств типом-владельцем

Хотя присоединенные свойства можно задавать для любого элемента языка XAML (или базового DependencyObject), это еще не означает, что задание свойства даст какой-либо ощутимый результат или значение свойства вообще будет доступно. Тип, определяющий присоединенное свойство, обычно придерживается одного из следующих сценариев.

  • Тип, определяющий присоединенное свойство, является родителем по отношению к другим объектам. Дочерние объекты будут устанавливать значения для присоединенного свойства. Тип-владелец присоединенного свойства имеет некоторое наследуемое поведение, которое повторяется в дочерних элементах, получает значения и работает с этими значениями в некоторой точке жизненного цикла объекта (выполняет такие действия, как создание структуры, SizeChanged и т. д.).
  • Тип, определяющий присоединенное свойство, используется в качестве дочернего элемента для ряда возможных родительских элементов и моделей содержимого, но информация не обязательно содержит информацию о структуре.
  • Присоединенное свойство сообщает информацию службе, а не другому элементу пользовательского интерфейса.

Более подробную информацию об этих сценариях и типах-владельцах см. в разделе "Подробно о Canvas.Left" темы Пользовательские присоединенные свойства.

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

У присоединенных свойств нет обычных оболочек свойств для простого доступа к методам доступа get/set, как у прочих свойств зависимостей. Причина этого в том, что присоединенное свойство не обязательно является частью объектной модели экземпляров (основанной на коде), для которых задано свойство. (Можно, хотя это обычно и не делается, определить свойство как присоединенное свойство, которое другие типы могут задавать для самих себя, и как используемое в качестве обычного свойства типом-владельцем.)

Есть два пути задания присоединенного свойства в коде: использование API системы свойств или использование шаблона метода доступа XAML. Данные методики в значительной степени равнозначны с точки зрения конечного результата, так что выбор одной из них зависит больше от предпочитаемого стиля программирования.

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

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

Для задания присоединенного свойства в коде вызовите метод SetValue и передайте поле DependencyProperty, служащее идентификатором этого присоединенного свойства. (Также можно передать значение, которое следует задать.)

Для получения значения присоединенного свойства в коде вызовите метод GetValue, опять же передавая поле DependencyProperty, которое служит идентификатором.

Использование шаблона метода доступа языка XAML

Процессор XAML должен иметь возможность установить значения присоединенного свойства, когда синтаксический анализ преобразует XAML в дерево объектов. Тип-владелец присоединенного свойства должен реализовать специальные методы доступа, указанные в форме GetPropertyName и SetPropertyName. Эти специальные методы доступа также являются одним из способов получения или задания присоединенного свойства через код. С точки зрения кода присоединенное свойство подобно резервному полю, у которого методы доступа к свойствам заменены на методы доступа к методам и которое может существовать в любом объекте, не нуждаясь в специальном определении.

Следующий пример показывает, как можно задать присоединенное свойство в коде, используя API метода доступа XAML. В этом примере myCheckBox является экземпляром класса CheckBox. Собственно задает значение последняя строка кода, строки перед ней просто устанавливают экземпляры и их иерархическое отношение. Раскомментированная последняя строка является синтаксисом, если вы используете систему свойств. Закомментированная последняя строка является синтаксисом, если вы используете шаблон метода доступа XAML.

    Canvas myC = new Canvas();
    CheckBox myCheckBox = new CheckBox();
    myCheckBox.Content = "Hello";
    myC.Children.Add(myCheckBox);
    myCheckBox.SetValue(Canvas.TopProperty,75);
    //Canvas.SetTop(myCheckBox, 75);
    Dim myC As Canvas = New Canvas()
    Dim myCheckBox As CheckBox= New CheckBox()
    myCheckBox.Content = "Hello"
    myC.Children.Add(myCheckBox)
    myCheckBox.SetValue(Canvas.TopProperty,75)
    ' Canvas.SetTop(myCheckBox, 75)
Canvas myC;
CheckBox myCheckBox;
myCheckBox.Content(winrt::box_value(L"Hello"));
myC.Children().Append(myCheckBox);
myCheckBox.SetValue(Canvas::TopProperty(), winrt::box_value(75));
// Canvas::SetTop(myCheckBox, 75);
    Canvas^ myC = ref new Canvas();
    CheckBox^ myCheckBox = ref new CheckBox();
    myCheckBox->Content="Hello";
    myC->Children->Append(myCheckBox);
    myCheckBox->SetValue(Canvas::TopProperty,75);
    // Canvas::SetTop(myCheckBox, 75);

Пользовательские присоединенные свойства

Примеры кода, определяющие особые присоединенные свойства, а также дополнительные сведения о сценариях использования присоединенных свойств см. в разделе Особые присоединенные свойства.

Специальный синтаксис для ссылок на присоединенные свойства

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

  • Чтобы обозначить присоединенное свойство как часть конечного пути для анимации, заключите имя присоединенного свойства в круглые скобки («()»), например, «(Canvas.Left)». Дополнительные сведения см. в разделе Синтаксис Property-path.

Предупреждение

Существующее ограничение реализации среда выполнения Windows XAML заключается в том, что вы не можете анимировать пользовательское присоединенное свойство.

  • Чтобы указать присоединенное свойство в качестве целевого свойства для ссылки на ресурс из файла ресурсов в x:Uid, используйте специальный синтаксис, который внедряет полный код, используя объявление в квадратных скобках ("[]"), чтобы создать преднамеренный область разрыв. Например, при условии, что существует элемент <TextBlock x:Uid="Title" />, ключ ресурса в файле ресурсов, который предназначен для Canvas.Top значения в этом экземпляре, — "Title".[ using:Windows.UI.Xaml.Controls]Canvas.Top". Подробнее о файле ресурсов и языке XAML см. в разделе Краткое руководство: перевод ресурсов пользовательского интерфейса.