Общие сведения о вложенных свойствах зависимостей

Вложенное свойство является понятием Extensible Application Markup Language (XAML). Вложенное свойство предназначено для использования в качестве типа глобального свойства, которое может быть задано для любого объекта. В Windows Presentation Foundation (WPF) вложенные свойства обычно определяются как особая форма свойства зависимости, не имеющая "оболочки" традиционного свойства.

В этом разделе содержатся следующие подразделы.

  • Предварительные требования
  • Зачем использовать вложенные свойства?
  • Вложенные свойства в XAML
  • Как вложенные свойства зависимостей используются типом-владельцем
  • Вложенные свойства в коде
  • Метаданные вложенного свойства
  • Пользовательские вложенные свойства
  • Дополнительные сведения о вложенных свойствах зависимостей
  • Связанные разделы

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

Этот раздел предполагает понимание свойств зависимости с точки зрения пользователя существующих свойств зависимости для классов Windows Presentation Foundation (WPF) и предварительное прочтение раздела Общие сведения о свойствах зависимости. Для понимания примеров в этом разделе также требуется понимать Extensible Application Markup Language (XAML) и знать порядок написания приложений WPF.

Зачем использовать вложенные свойства?

Одним из назначений вложенного свойства является разрешение различным дочерним элементам задавать уникальные значения для свойства, которое фактически определено в родительском элементе. Конкретным применением этого скрипта является предписание дочерним элементам информировать родительский элемент о порядке их представления в user interface (UI). Одним из примеров является свойство DockPanel.Dock. Свойство DockPanel.Dock создается как вложенное свойство, поскольку оно предназначено для элементов, содержащихся в DockPanel, а не для самого DockPanel. Класс DockPanel определяет статическое поле DependencyProperty с именем DockProperty, а затем предоставляет методы GetDock и SetDock как открытые методы доступа для вложенного свойства.

Вложенные свойства в XAML

В XAML вложенные свойства задаются с использованием синтаксиса AttachedPropertyProvider.PropertyName 

Ниже приведен пример задания свойства DockPanel.Dock в XAML:

<DockPanel>
  <CheckBox DockPanel.Dock="Top">Hello</CheckBox>
</DockPanel>

Обратите внимание, что данное использование в чем-то похоже на статическое свойство; всегда используется ссылка на тип DockPanel, который является владельцем и регистрирует вложенное свойство, а не ссылка на экземпляр по указанному имени.

Кроме того, поскольку вложенное свойство в XAML является атрибутом, который устанавливается в макете, какое-либо значение имеет только операция Set. Нельзя непосредственно получить свойство в XAML, хотя существуют некоторые косвенные механизмы для сравнения значений, такие как триггеры в стилях (подробнее см. в разделе Стилизация и использование шаблонов).

Реализация вложенного свойства в WPF

В Windows Presentation Foundation (WPF) большинство вложенных свойств, существующих для типов WPF, реализовано как свойства зависимости. Вложенные свойства являются понятием XAML, тогда как свойства зависимости являются понятием WPF. Поскольку вложенные свойства WPF являются свойствами зависимости, они поддерживают такие понятия свойств зависимости, как метаданные свойства, а также значения по умолчанию из этих метаданных свойства.

Как вложенные свойства зависимостей используются типом-владельцем

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

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

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

  • Тип, который определяет вложенное свойство, представляет службу. Другие типы устанавливают значения для вложенного свойства. Затем, когда задающий свойство элемент вычисляется в контексте службы, получение значений вложенных свойств выполняется с помощью внутренней логики класса службы.

Пример вложенного свойства, определенного родительским элементом

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

DockPanel определяет вложенное свойство DockPanel.Dock, а DockPanel содержит код на уровне класса как часть логики отрисовки (в частности, MeasureOverride и ArrangeOverride). Экземпляр DockPanel будет всегда проверять, установил ли какой-либо непосредственный дочерний элемент значение для DockPanel.Dock. Если значения установлены, они становятся входными данными для логики отрисовки, применяемой к соответствующему дочернему элементу. Каждый вложенный экземпляр DockPanel интерпретирует коллекции своих непосредственных дочерних элементов, но это поведение зависит от реализации того, как DockPanel обрабатывает значения DockPanel.Dock. Теоретически возможно иметь вложенные свойства, оказывающие влияние на элементы за пределами непосредственного родителя. Если вложенное свойство DockPanel.Dock установлено для элемента, который не имеет действующего на него родительского элемента DockPanel, ошибка или исключение не возникает. Это означает лишь, что было задано глобальное значение свойства, но оно не имеет текущего родительского элемента DockPanel, который мог бы использовать эту информацию.

Вложенные свойства в коде

Вложенные свойства в WPF не имеют обычной CLR "оболочки" методов доступа Get/Set. Это обусловлено тем, что вложенное свойство не обязательно является частью пространства имен CLR для экземпляров, в которых оно задано. Однако считыватель XAML должен иметь возможность задавать эти значения при обработке XAML. Для эффективности вложенного свойства зависимостей тип-владелец вложенного свойства зависимостей должен реализовывать выделенные методы доступа в форме GetPropertyName и SetPropertyName. Эти выделенные методы доступа также используются для получения или задания вложенного свойства в коде. С точки зрения кода вложенное свойство идентично резервному полю, имеющему метод доступа вместо метода доступа к свойству, и это резервное поле может существовать для любого объекта, не требуя специального определения.

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

      Dim myDockPanel As New DockPanel()
      Dim myCheckBox As New CheckBox()
      myCheckBox.Content = "Hello"
      myDockPanel.Children.Add(myCheckBox)
      DockPanel.SetDock(myCheckBox, Dock.Top)
DockPanel myDockPanel = new DockPanel();
CheckBox myCheckBox = new CheckBox();
myCheckBox.Content = "Hello";
myDockPanel.Children.Add(myCheckBox);
DockPanel.SetDock(myCheckBox, Dock.Top);

Аналогично случаю с XAML, если myCheckBox не добавлен как дочерний элемент myDockPanel третьей строкой кода, то четвертая строка кода не приведет к исключению, но значение свойства не будет взаимодействовать с родительским элементом DockPanel и, следовательно, не будет ни на что влиять. Только значение DockPanel.Dock, заданное для дочернего элемента, в сочетании с наличием родительского элемента DockPanel, будет влиять на поведение в отображаемом приложении. (В этом случае, вы можете задать вложенное свойство и затем присоединить его к дереву. Или вы можете присоединить его к дереву, а затем задать вложенное свойство. Любая последовательность действий приведет к одному и тому же результату.)

Метаданные вложенного свойства

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

Если требуется разрешить наследование значения свойства, следует использовать вложенные свойства вместо неприсоединяемых свойств зависимости. Дополнительные сведения см. в разделе Наследование значения свойства.

Пользовательские вложенные свойства

Когда следует создавать вложенное свойство

Вложенное свойство можно создать при наличии потребности в механизме задания свойств, доступного для классов, отличных от определяющего класса. Чаще всего этого требует макет. Примерами существующих свойств макета являются DockPanel.Dock, Panel.ZIndex и Canvas.Top. В данном случае элементы, которые существуют как дочерние для элементов управления макетом, имеют возможность индивидуально выражать требования макета к своим родительским элементам макета, задавая значение свойства, определяемое родительским элементом как вложенное свойство.

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

Еще одним случаем является получение поддержки Visual Studio 2008 сред. Конструктор WPF, например, для редактирования окнасвойств. Дополнительные сведения см. в разделе Общие сведения о разработке управления.

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

Как создать вложенное свойство

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

Определите вложенное свойство как свойство зависимости, объявив поле publicstatic readonly типа DependencyProperty. Для определения этого поля используется возвращаемое значение метода RegisterAttached. Имя поля должно совпадать с именем вложенного свойства с добавлением строки Property, чтобы следовать установленному шаблону именования идентифицирующих полей WPF и свойств, которые они представляют. Поставщик вложенного свойства зависимостей также должен предоставлять статические методы GetPropertyName и SetPropertyName как методы доступа для вложенных свойств зависимостей; если этого не сделать, система свойств не сможет использовать вложенное свойство зависимостей.

ПримечаниеПримечание

Если опустить метод доступа Get вложенного свойства, привязка данных для этого свойства не будет действовать в средствах разработки, таких как Visual Studio и Expression Blend.

Метод доступа Get

Сигнатура для метода доступа GetPropertyName должна быть следующей:

public static object GetPropertyName(object target)

  • Объект target может быть задан в реализации как более конкретный тип. Например, метод DockPanel.GetDock определяет тип параметра как UIElement, поскольку только вложенное свойство предназначено для установки только на экземплярах UIElement.

  • Возвращаемое значение может быть задано в реализации как более конкретный тип. Например, метод GetDock определяет его тип как Dock, поскольку в качестве значения может быть установлена только это перечисление.

Метод доступа Set

Сигнатура для метода доступа SetИмяСвойства должна быть следующей:

public static void SetPropertyName(object target, object value)

  • Объект target может быть задан в реализации как более конкретный тип. Например, метод SetDock определяет тип параметра как UIElement, поскольку только вложенное свойство предназначено для установки только на экземплярах UIElement.

  • Объект value может быть задан в реализации как более конкретный тип. Например, метод SetDock определяет его тип как Dock, поскольку в качестве значения может быть установлена только это перечисление. Помните, что значением для данного метода являются входные данные, поступающие от загрузчика XAML, когда он встречает вложенное свойство в использовании вложенного свойства в макете. Эти входные данные являются значением, заданным как значение атрибута XAML в макете. Поэтому должно существовать такое преобразование типов, сериализатор значения или поддержка расширения макета для используемого типа, чтобы можно было создать соответствующий тип из значения атрибута (которое в конечном счете является строкой).

Следующий пример демонстрирует регистрацию свойства зависимости (с использованием метода RegisterAttached), а также методы доступа GetPropertyName и SetPropertyName. В этом примере вложенное свойство имеет имя IsBubbleSource. Следовательно, методы доступа должны иметь имена GetIsBubbleSource и SetIsBubbleSource.

Public Shared ReadOnly IsBubbleSourceProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsBubbleSource", GetType(Boolean), GetType(AquariumObject), New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.AffectsRender))
Public Shared Sub SetIsBubbleSource(ByVal element As UIElement, ByVal value As Boolean)
    element.SetValue(IsBubbleSourceProperty, value)
End Sub
Public Shared Function GetIsBubbleSource(ByVal element As UIElement) As Boolean
    Return CType(element.GetValue(IsBubbleSourceProperty), Boolean)
End Function
public static readonly DependencyProperty IsBubbleSourceProperty = DependencyProperty.RegisterAttached(
  "IsBubbleSource",
  typeof(Boolean),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static void SetIsBubbleSource(UIElement element, Boolean value)
{
  element.SetValue(IsBubbleSourceProperty, value);
}
public static Boolean GetIsBubbleSource(UIElement element)
{
  return (Boolean)element.GetValue(IsBubbleSourceProperty);
}

Атрибуты вложенного свойства

WPF определяет несколько .NET Framework attributes, которые предназначены для предоставления сведений о вложенных свойствах процессам отражения и обычным пользователям отражения и сведений о свойствах, таким как конструкторы. Поскольку вложенные свойства имеют тип неограниченной области, конструкторам необходим способ избежания переполнения пользователей глобальным списком всех вложенных свойств, которые определены в конкретной реализации технологии, использующей XAML. .NET Framework attributes, определяемый WPF для вложенных свойств, может быть использован для ситуаций, когда данное вложенное свойство должно отображаться в окне свойств. Можно также применить эти атрибуты для собственных пользовательских вложенных свойств. Назначение и синтаксис .NET Framework attributes описаны на соответствующих страницах справочника:

Дополнительные сведения о вложенных свойствах зависимостей

  • Дополнительные сведения о создании вложенных свойств зависимостей см. в разделе Практическое руководство. Регистрация вложенного свойства зависимостей.

  • Дополнительные случаи использования свойств зависимостей и вложенных свойств зависимостей см. в разделе Пользовательские свойства зависимостей.

  • Можно также зарегистрировать свойство как вложенное свойство и как свойство зависимости, но затем по-прежнему предоставлять реализации "оболочки". В этом случае свойство может быть задано либо для этого элемента, либо для любого элемента через синтаксис XAMLвложенного свойства. Примером свойства с соответствующим скриптом для стандартного и вложенного использования является FrameworkElement.FlowDirection.

См. также

Задачи

Практическое руководство. Регистрация вложенного свойства зависимостей

Ссылки

DependencyProperty

Основные понятия

Общие сведения о свойствах зависимости

Пользовательские свойства зависимостей

Общие сведения о языке XAML (WPF)