Метаданные свойства зависимостей (WPF .NET)

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

Важно!

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

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

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

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

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

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

  • Ссылки на обратные вызовы значений приведения и обратные вызовы изменения свойств для типа владельца. Вы можете получить ссылки только на обратные вызовы с модификатором доступа public или в пределах разрешенной области доступа. Дополнительные сведения об обратных вызовах свойств зависимости см. в разделе Обратные вызовы и проверка свойств зависимости.

  • Характеристики свойства зависимостей на уровне платформы WPF (если свойство зависимостей является свойством платформы WPF). Процессы WPF, такие как подсистема макета платформы и логика наследования свойств, запрашивают метаданные на уровне платформы WPF. Дополнительные сведения см. в разделе Метаданные свойств платформы.

API метаданных

Класс PropertyMetadata хранит большую часть метаданных, используемых системой свойств. Экземпляры метаданных могут создавать и назначать следующими объекты:

  • Типы, которые регистрируют свойства зависимостей в системе свойств.

  • Типы, которые наследуют из класса, определяющего свойство зависимостей.

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

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

Чтобы получить метаданные для свойства зависимостей, вызовите одну из перегрузок GetMetadata идентификатора DependencyProperty. Метаданные возвращаются как объект PropertyMetadata.

Для разных архитектурных областей существуют более конкретные классы метаданных, производные от PropertyMetadata. Например, UIPropertyMetadata поддерживает отчеты об анимации, а FrameworkPropertyMetadata — свойства платформы WPF. Свойства зависимостей также можно регистрировать с помощью производных классов PropertyMetadata. Хотя GetMetadata возвращает объект PropertyMetadata, при необходимости возможно приведение к производному типу для проверки свойств, характерных для типа.

Характеристики свойства, предоставляемые FrameworkPropertyMetadata, иногда называются флагами. При создании экземпляра FrameworkPropertyMetadata экземпляр типа перечисления FrameworkPropertyMetadataOptions можно передать конструктору FrameworkPropertyMetadata. FrameworkPropertyMetadataOptions позволяет указать флаги метаданных в побитовом сочетании. FrameworkPropertyMetadata использует FrameworkPropertyMetadataOptions для разумного сохранения длины сигнатуры конструктора. При регистрации свойств зависимостей флаги метаданных, заданные в FrameworkPropertyMetadataOptions, предоставляются в FrameworkPropertyMetadata виде свойств Boolean, а не побитового сочетания флагов, чтобы сделать запросы характеристик метаданных более интуитивно понятными.

Переопределение или создание новых метаданных?

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

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

Сценарии переопределения метаданных

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

  • Изменение значения по умолчанию — распространенный сценарий.

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

  • Изменение параметров метаданных свойств платформы WPF. Как правило, параметры метаданных задаются во время регистрации нового свойства зависимостей, но их можно изменить в вызовах OverrideMetadata или AddOwner. Дополнительные сведения о переопределении метаданных свойств платформы см. в разделе "Указание frameworkPropertyMetadata". Сведения о настройке параметров метаданных свойств платформы при регистрации свойства зависимостей см. в статье Пользовательские свойства зависимостей.

Примечание.

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

Переопределение метаданных

При реализации нового свойства зависимостей можно задать его метаданные с помощью перегрузок метода Register. Если класс наследует свойство зависимостей, унаследованные значения метаданных можно переопределить с помощью метода OverrideMetadata. Например, с помощью OverrideMetadata можно задать значения, относящиеся к типу. Дополнительные сведения, включая примеры кода, см. в статье Переопределение метаданных для свойства зависимости.

Пример свойства зависимостей WPF: Focusable. Класс FrameworkElement регистрирует Focusable. Класс Control, производный от FrameworkElement, наследует свойство зависимостей Focusable и переопределяет метаданные унаследованного свойства. Переопределение меняет значение свойства по умолчанию с falseна true, но сохраняет другие унаследованные значения метаданных.

Так как большинство существующих свойств зависимостей не являются виртуальными свойствами, их унаследованная реализация затемняет существующий член. При переопределении характеристики метаданных новое значение метаданных либо заменяет исходное значение, либо они объединяются:

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

  • Для параметра PropertyChangedCallbackлогика слияния по умолчанию сохраняет все значения PropertyChangedCallback в таблице и все они вызываются при изменении свойства. Порядок обратного вызова определяется глубиной класса, т. е. обратный вызов, зарегистрированный базовым классом в иерархии, выполняется первым.

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

Примечание.

Логика слияния по умолчанию реализуется методом Merge. Пользовательскую логику слияния можно указать в производном классе, наследующем свойство зависимостей, переопределив Merge в этом классе.

Добавление класса в качестве владельца

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

  • Поле идентификатора свойства зависимостей. Значение идентификатора свойства зависимостей — это возвращаемое значение вызова AddOwner. Это поле должно быть полем public static readonly типа DependencyProperty.

  • Оболочка среды CLR, реализующая методы доступа get и set. Используя оболочку свойств, объекты-получатели свойств зависимостей могут получать или задавать значения свойств зависимостей так же, как и любое другое свойство CLR. Методы доступа get и set взаимодействуют с базовой системой свойств посредством вызовов DependencyObject.GetValue и DependencyObject.SetValue, передавая идентификатор свойства зависимостей в качестве параметра. Реализуйте оболочку так же, как при регистрации пользовательского свойства зависимостей. Дополнительные сведения см. в статье Пользовательские свойства зависимостей.

Класс, который вызывает AddOwner, имеет те же требования для предоставления объектной модели унаследованного свойства зависимости в качестве класса, определяющего новое пользовательское свойство зависимостей. Дополнительные сведения см. в статье Добавление типа владельца для свойства зависимостей.

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

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

Примечание.

Для регистрации свойств всегда используйте RegisterAttached, если в метаданных указываете Inherits. Хотя для неприсоединенных свойств зависимостей возможно наследование значений, поведение наследования для таких свойств не определено при переходе через определенные границы элементов в дереве среды выполнения. Свойство Inherits не относится к неприсоединенным свойствам. Для получения дополнительных сведения см. RegisterAttached(String, Type, Type, PropertyMetadata) в разделе примечаний свойства Inherits.

Добавление класса в качестве владельца присоединенного свойства

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

  • Вызовите AddOwner, чтобы добавить свой класса в качестве владельца присоединенного свойства зависимостей.

  • Назначьте возвращаемое значение вызова AddOwner полю public static readonly для использования в качестве идентификатора свойства зависимостей.

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

См. также