Общие сведения о присоединенных свойствах (WPF .NET)

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

Важно!

Документация по рабочему столу для .NET 7 и .NET 6 находится в стадии разработки.

Необходимые компоненты

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

Почему используют присоединенные свойства

Присоединенное свойство позволяет дочернему элементу указать уникальное значение для свойства, определенного в родительском элементе. Распространенный сценарий — это дочерний элемент, указывающий, как он должен быть отображен в пользовательском интерфейсе его родительским элементом. Например, это присоединенное свойство, DockPanel.Dock так как оно задано для дочерних элементов объекта DockPanel, а не DockPanel самого. Класс DockPanel определяет статическое DependencyProperty поле с именем DockProperty, а затем предоставляет GetDock и SetDock методы в качестве общедоступных методов доступа для присоединенного свойства.

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

В XAML вы задаете присоединенные свойства с помощью синтаксиса <attached property provider type>.<property name>, где присоединенный поставщик свойств является классом, определяющим присоединенное свойство. В следующем примере показано, как дочерний DockPanel элемент может задать DockPanel.Dock значение свойства.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

Использование аналогично статическому свойству, которое ссылается на тип, принадлежащий и регистрирующий присоединенное свойство (например, DockPanel), а не имя экземпляра.

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

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

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

Модели использования присоединенных свойств

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

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

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

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

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

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

Присоединенные свойства в WPF не имеют типичных методов CLR get и set оболочки, так как свойства могут быть заданы вне пространства имен CLR. Чтобы разрешить обработчику XAML задать эти значения при анализе XAML, класс, определяющий присоединенное свойство, должен реализовать выделенные методы доступа в виде Get<property name> и Set<property name>.

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

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Если вы не добавляете myTextBox в качестве дочернего элемента, вызов SetDock не вызовет исключение или не имеет никакого myDockPanelэффекта. DockPanel.Dock Только значение, заданное в дочернем элементе, DockPanel может повлиять на отрисовку, и отрисовка будет совпадать с тем, задано ли значение до или после добавления дочернего элемента в объектDockPanel.

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

Метаданные присоединенного свойства

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

Чтобы включить наследование значений свойств для свойства, используйте присоединенные свойства вместо не присоединенных свойств зависимостей. Дополнительные сведения см. в разделе "Наследование значений свойств".

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

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

Создание присоединенного свойства полезно при следующих случаях:

  • Вам нужен механизм настройки свойства, доступный для классов, отличных от определяющего класса. Распространенный сценарий — это макет пользовательского интерфейса, напримерDockPanel.DockPanel.ZIndex, и Canvas.Top все примеры существующих свойств макета. В сценарии макета дочерние элементы элемента управления макетом могут выразить требования к макету родительскому элементу макета и задать значение для присоединенного свойства, определенного родительским элементом.

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

  • Вам нужна поддержка конструктора WPF Visual Studio, например возможность редактирования свойства в окне "Свойства ". Дополнительные сведения см. в разделе "Обзор разработки элементов управления".

  • Вы хотите использовать наследование значений свойств.

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

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

Определите присоединенное свойство как зависимость в определяемом public static readonly классе, объявив поле типа DependencyProperty. Затем назначьте возвращаемое значение RegisterAttached метода полю, которое также называется идентификатором свойства зависимостей. Следуйте соглашению об именовании свойств WPF, которое отличает поля от свойств, которые они представляют, именуя поле <property name>Propertyидентификатора. Кроме того, предоставьте статические Get<property name> и Set<property name> методы доступа, которые позволяют системе свойств получить доступ к присоединенному свойству.

В следующем примере показано, как зарегистрировать свойство зависимостей с помощью RegisterAttached метода и как определить методы доступа. В примере имя присоединенного свойства имеет значениеHasFish, поэтому поле идентификатора называется, а методы доступа именуются HasFishPropertyGetHasFish иSetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

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

Сигнатура get метода доступа:public static object Get<property name>(DependencyObject target)

  • target — это свойство DependencyObject , из которого считывается присоединенное свойство. Тип target может быть более конкретным, чем DependencyObject. Например, DockPanel.GetDock метод доступа вводит тип target , так как UIElement присоединенное свойство предназначено для задания экземпляров UIElement . UiElement косвенно является производным от DependencyObject.
  • Тип возвращаемого значения может быть более конкретным, чем object. Например, GetDock метод вводит возвращаемое значение, так как Dock возвращаемое значение должно быть Dock перечислением.

Примечание.

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

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

Сигнатура set метода доступа:public static void Set<property name>(DependencyObject target, object value)

  • targetDependencyObject— значение, на котором записывается присоединенное свойство. Тип target может быть более конкретным, чем DependencyObject. Например, SetDock метод типы target , так как UIElement присоединенное свойство предназначено для задания экземпляров UIElement . UiElement косвенно является производным от DependencyObject.
  • Тип value может быть более конкретным, чем object. Например, методу SetDock требуется Dock значение. Загрузчик XAML должен иметь возможность создать value тип из строки разметки, представляющей значение присоединенного свойства. Таким образом, необходимо иметь поддержку преобразования типов, сериализатора значений или расширения разметки для используемого типа.

Атрибуты присоединенного свойства

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

Подробнее

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

См. также