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

В этом разделе описываются основания для создания настраиваемых свойств зависимостей для приложений Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF), а также этапы и некоторые варианты реализации, которые могут повысить производительность, удобство использования и универсальность свойств.This topic describes the reasons that Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) application developers and component authors might want to create custom dependency property, and describes the implementation steps as well as some implementation options that can improve performance, usability, or versatility of the property.

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

Предполагается, что вы имеете представление о свойствах зависимостей с точки зрения потребителя существующих свойств зависимостей в классах WPFWPF и ознакомились с разделом Общие сведения о свойствах зависимостей.This topic assumes that you understand dependency properties from the perspective of a consumer of existing dependency properties on WPFWPF classes, and have read the Dependency Properties Overview topic. Чтобы выполнить примеры в этом разделе, следует также иметь представление о Язык XAMLExtensible Application Markup Language (XAML) и написании приложений WPFWPF.In order to follow the examples in this topic, you should also understand Язык XAMLExtensible Application Markup Language (XAML) and know how to write WPFWPF applications.

Что такое свойство зависимостей?What Is a Dependency Property?

Чтобы обеспечить поддержку стилей, привязки данных, наследования, анимации и значений по умолчанию, можно включить свойство среды CLR, которое в противном случае будет реализовано как свойство зависимостей.You can enable what would otherwise be a common language runtime (CLR) property to support styling, data binding, inheritance, animations, and default values by implementing it as a dependency property. Свойства зависимостей — это свойства, регистрируемые в системе свойств WPFWPF путем вызова метода Register (или RegisterReadOnly), которые поддерживаются полем идентификатора DependencyProperty.Dependency properties are properties that are registered with the WPFWPF property system by calling the Register method (or RegisterReadOnly), and that are backed by a DependencyProperty identifier field. Свойства зависимостей могут использоваться только типами DependencyObject, но DependencyObject довольно высоки в иерархии классов WPFWPF, поэтому большинство классов, доступных в WPFWPF, могут поддерживать свойства зависимостей.Dependency properties can be used only by DependencyObject types, but DependencyObject is quite high in the WPFWPF class hierarchy, so the majority of classes available in WPFWPF can support dependency properties. Дополнительные сведения о свойствах зависимостей и некоторых терминологиях и соглашениях, используемых для их описания в этом пакете SDK, см. в разделе Общие сведения о свойствах зависимостей.For more information about dependency properties and some of the terminology and conventions used for describing them in this SDK, see Dependency Properties Overview.

Примеры свойств зависимостейExamples of Dependency Properties

Примеры свойств зависимостей, реализованных в WPFWPF классах, включают свойство Background, свойство Width и свойство Text, среди многих других.Examples of dependency properties that are implemented on WPFWPF classes include the Background property, the Width property, and the Text property, among many others. Каждое свойство зависимости, предоставляемое классом, имеет соответствующее открытое статическое поле типа DependencyProperty предоставленное в этом же классе.Each dependency property exposed by a class has a corresponding public static field of type DependencyProperty exposed on that same class. Это идентификатор для свойства зависимостей.This is the identifier for the dependency property. Идентификатор именуется по следующему соглашению: имя свойства зависимостей, за которым следует строка Property.The identifier is named using a convention: the name of the dependency property with the string Property appended to it. Например, соответствующее поле идентификатора DependencyProperty для свойства Background BackgroundProperty.For example, the corresponding DependencyProperty identifier field for the Background property is BackgroundProperty. Идентификатор хранит сведения о свойстве зависимостей в том виде, в котором оно было зарегистрировано, а идентификатор затем используется позже для других операций, использующих свойство зависимостей, например вызов SetValue.The identifier stores the information about the dependency property as it was registered, and the identifier is then used later for other operations involving the dependency property, such as calling SetValue.

Как упоминалось в разделе Общие сведения о свойствах зависимостей, все свойства зависимостей в WPFWPF (за исключением большинства присоединенных свойств) также являются свойствами CLR из-за реализации "оболочки".As mentioned in the Dependency Properties Overview, all dependency properties in WPFWPF (except most attached properties) are also CLR properties because of the "wrapper" implementation. Таким образом, из кода можно получить или задать свойства зависимостей, вызвав методы доступа CLR, которые определяют оболочки так же, как и другие свойства среды CLR.Therefore, from code, you can get or set dependency properties by calling CLR accessors that define the wrappers in the same manner that you would use other CLR properties. Как потребитель установленных свойств зависимостей, обычно не используются методы DependencyObject GetValue и SetValue, которые являются точкой подключения к базовой системе свойств.As a consumer of established dependency properties, you do not typically use the DependencyObject methods GetValue and SetValue, which are the connection point to the underlying property system. Вместо этого существующая реализация свойств CLR уже будет называться GetValue и SetValue в реализации оболочки get и set свойства, используя поле идентификатора соответствующим образом.Rather, the existing implementation of the CLR properties will have already called GetValue and SetValue within the get and set wrapper implementations of the property, using the identifier field appropriately. При собственной реализации настраиваемого свойства зависимостей вы будете определять оболочку аналогичным образом.If you are implementing a custom dependency property yourself, then you will be defining the wrapper in a similar way.

Почему требуется реализовывать свойство зависимостей?When Should You Implement a Dependency Property?

При реализации свойства в классе, если класс является производным от DependencyObject, вы можете вернуть свойство с помощью идентификатора DependencyProperty и, таким образом, сделать его свойством зависимостей.When you implement a property on a class, so long as your class derives from DependencyObject, you have the option to back your property with a DependencyProperty identifier and thus to make it a dependency property. Назначение свойства свойством зависимостей не всегда требуется и не всегда уместно и зависит от конкретной ситуации.Having your property be a dependency property is not always necessary or appropriate, and will depend on your scenario needs. В некоторых случаях достаточно просто снабдить свойство закрытым полем.Sometimes, the typical technique of backing your property with a private field is adequate. Тем не менее реализовать свойство как свойство зависимостей потребуется, если свойство должно поддерживать одну или несколько из следующих возможностей WPFWPF.However, you should implement your property as a dependency property whenever you want your property to support one or more of the following WPFWPF capabilities:

  • Требуется, чтобы свойство было задаваемым в стиле.You want your property to be settable in a style. Более подробную информацию см. в разделе Стилизация и использование шаблонов.For more information, see Styling and Templating.

  • Требуется, чтобы свойство поддерживало привязку данных.You want your property to support data binding. Дополнительные сведения о свойствах зависимостей привязки данных см. в разделе Привязка свойств двух элементов управления.For more information about data binding dependency properties, see Bind the Properties of Two Controls.

  • Требуется, чтобы свойство было задаваемым с помощью динамической ссылки ресурса.You want your property to be settable with a dynamic resource reference. Дополнительные сведения см. в разделе Ресурсы XAML.For more information, see XAML Resources.

  • Требуется настроить автоматическое наследование значения свойства из родительского элемента в дереве элементов.You want to inherit a property value automatically from a parent element in the element tree. В этом случае Зарегистрируйтесь в методе RegisterAttached, даже если также создается оболочка свойств для доступа к среде CLR.In this case, register with the RegisterAttached method, even if you also create a property wrapper for CLR access. Дополнительные сведения см. в разделе Наследование значения свойства.For more information, see Property Value Inheritance.

  • Требуется, чтобы свойство поддерживало анимацию.You want your property to be animatable. Более подробную информацию см. в разделе Общие сведения об эффектах анимации.For more information, see Animation Overview.

  • Требуется, чтобы система свойств сообщала об изменении предыдущего значения свойства действиями, выполняемыми системой свойств, окружением или пользователем, или путем чтения и использования стилей.You want the property system to report when the previous value of the property has been changed by actions taken by the property system, the environment, or the user, or by reading and using styles. Используя метаданные свойства, свойство может указывать метод обратного вызова, который будет вызываться каждый раз, когда система свойств определит, что значение свойства было однозначно изменено.By using property metadata, your property can specify a callback method that will be invoked each time the property system determines that your property value was definitively changed. Связанным понятием является приведение значения свойства.A related concept is property value coercion. Дополнительные сведения см. в разделе Проверка и обратные вызовы свойства зависимостей.For more information, see Dependency Property Callbacks and Validation.

  • Требуется использовать установленные соглашения о метаданных, которые также используются процессами WPFWPF, такими как передача сведений о том, нужно ли системе макета перестраивать визуальные компоненты элемента при изменении значения свойства.You want to use established metadata conventions that are also used by WPFWPF processes, such as reporting whether changing a property value should require the layout system to recompose the visuals for an element. Или требуется возможность использовать переопределения метаданных таким образом, чтобы производные классы могли изменять основанные на метаданных характеристики, такие как значение по умолчанию.Or you want to be able to use metadata overrides so that derived classes can change metadata-based characteristics such as the default value.

  • Необходимо, чтобы свойства пользовательского элемента управления получали поддержку конструктора WPF Visual Studio, например изменение окна свойств .You want properties of a custom control to receive Visual Studio WPF Designer support, such as Properties window editing. Дополнительные сведения см. в разделе Общие сведения о разработке элементов управления.For more information, see Control Authoring Overview.

Рекомендуется рассмотреть возможность реализации сценариев путем переопределения метаданных существующего свойства зависимостей, вместо реализации совершенно нового свойства.When you examine these scenarios, you should also consider whether you can achieve your scenario by overriding the metadata of an existing dependency property, rather than implementing a completely new property. Практическая польза переопределения метаданных зависит от сценария и того, насколько этот сценарий схож с реализацией существующих свойств зависимостей и классов WPFWPF.Whether a metadata override is practical depends on your scenario and how closely that scenario resembles the implementation in existing WPFWPF dependency properties and classes. Дополнительные сведения о переопределении метаданных для существующих свойств см. в разделе Метаданные свойств зависимостей.For more information about overriding metadata on existing properties, see Dependency Property Metadata.

Контрольный список определения свойства зависимостейChecklist for Defining a Dependency Property

Определение свойства зависимостей состоит из четырех различных понятий.Defining a dependency property consists of four distinct concepts. Эти понятия не обязательно являются строгими этапами процедуры, так как некоторые из них в итоге объединяются в одну строку кода в реализации.These concepts are not necessarily strict procedural steps, because some of these end up being combined as single lines of code in the implementation:

  • (Необязательно.) Создайте метаданные для свойства зависимостей.(Optional) Create property metadata for the dependency property.

  • Зарегистрируйте имя свойства в системе свойств, указав тип владельца и тип значения свойства.Register the property name with the property system, specifying an owner type and the type of the property value. Также укажите метаданные свойства, если они используются.Also specify the property metadata, if used.

  • Определите идентификатор DependencyProperty как public static readonly поля в типе владельца.Define a DependencyProperty identifier as a public static readonly field on the owner type.

  • Определите свойство "оболочка" среды CLR, имя которого соответствует имени свойства зависимостей.Define a CLR "wrapper" property whose name matches the name of the dependency property. Реализуйте get свойства оболочки CLR, а set методы доступа для соединения со свойством зависимостей, которое его создает.Implement the CLR "wrapper" property's get and set accessors to connect with the dependency property that backs it.

Регистрация свойства в системе свойствRegistering the Property with the Property System

Чтобы назначить свойство свойством зависимостей, необходимо зарегистрировать это свойство в таблице, обслуживаемой системой свойств, и предоставить ему уникальный идентификатор, используемый в качестве квалификатора для последующих операций системы свойств.In order for your property to be a dependency property, you must register that property into a table maintained by the property system, and give it a unique identifier that is used as the qualifier for later property system operations. Эти операции могут быть внутренними операциями или собственным кодом, вызывающим API системы свойств.These operations might be internal operations, or your own code calling property system APIs. Чтобы зарегистрировать свойство, вызовите метод Register в теле класса (внутри класса, но за пределами определений членов).To register the property, you call the Register method within the body of your class (inside the class, but outside of any member definitions). Поле идентификатора также предоставляется вызовом метода Register в качестве возвращаемого значения.The identifier field is also provided by the Register method call, as the return value. Причина, по которой вызов Register выполняется за пределами других определений элементов, заключается в том, что это возвращаемое значение используется для назначения и создания public static readonly поля типа DependencyProperty как часть класса.The reason that the Register call is done outside of other member definitions is because you use this return value to assign and create a public static readonly field of type DependencyProperty as part of your class. Это поле становится идентификатором для вашего свойства зависимостей.This field becomes the identifier for your dependency property.

public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender, 
      new PropertyChangedCallback(OnUriChanged)
  )
);
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = DependencyProperty.Register("AquariumGraphic", GetType(Uri), GetType(AquariumObject), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf OnUriChanged)))

Соглашения об именовании свойств зависимостейDependency Property Name Conventions

Существуют установленные соглашения об именовании, касающиеся свойств зависимостей, которым необходимо следовать, если ситуация не является исключительной.There are established naming conventions regarding dependency properties that you must follow in all but exceptional circumstances.

Само свойство зависимости будет иметь базовое имя «Акуариумграфик», как в этом примере, которое задается в качестве первого параметра Register.The dependency property itself will have a basic name, "AquariumGraphic" as in this example, which is given as the first parameter of Register. Это имя должно быть уникальным в пределах каждого регистрирующего типа.That name must be unique within each registering type. Считается, что свойства зависимостей, наследуемые через базовые типы, уже являются частью регистрирующего типа: имена наследуемых свойств нельзя зарегистрировать повторно.Dependency properties inherited through base types are considered to be already part of the registering type; names of inherited properties cannot be registered again. Однако существует способ добавления класса как владельца свойства зависимостей даже в том случае, если это свойство зависимостей не наследуется. Дополнительные сведения см. в разделе Метаданные свойств зависимостей.However, there is a technique for adding a class as owner of a dependency property even when that dependency property is not inherited; for details, see Dependency Property Metadata.

При создании поля идентификатора назовите это поле по зарегистрированному имени свойства, добавив суффикс Property.When you create the identifier field, name this field by the name of the property as you registered it, plus the suffix Property. Это поле является идентификатором для свойства зависимостей, которое будет использоваться в качестве входных данных для SetValue и GetValue вызовов, которые будут выполняться в оболочках любым другим кодом при доступе к свойству с помощью вашего собственного кода. , благодаря любому доступному внешнему коду в системе свойств и, возможно, XAMLXAML процессорах.This field is your identifier for the dependency property, and it will be used later as an input for the SetValue and GetValue calls you will make in the wrappers, by any other code access to the property by your own code, by any external code access you allow, by the property system, and potentially by XAMLXAML processors.

Примечание

Определение свойства зависимостей в теле класса является обычной реализацией, однако его также можно определить в статическом конструкторе класса.Defining the dependency property in the class body is the typical implementation, but it is also possible to define a dependency property in the class static constructor. Этот подход может оказаться целесообразным, если для инициализации свойства зависимостей требуется несколько строк кода.This approach might make sense if you need more than one line of code to initialize the dependency property.

Реализация "оболочки"Implementing the "Wrapper"

Реализация программы-оболочки должна вызывать GetValue в реализации get и SetValue в реализации set (исходный вызов регистрации и поле также отображаются здесь для ясности).Your wrapper implementation should call GetValue in the get implementation, and SetValue in the set implementation (the original registration call and field are shown here too for clarity).

Во всех, но исключительных обстоятельствах реализации оболочек должны выполнять только действия GetValue и SetValue соответственно.In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue actions, respectively. Причина этого обсуждается в разделе Загрузка кода XAML и свойства зависимостей.The reason for this is discussed in the topic XAML Loading and Dependency Properties.

Все существующие открытые свойства зависимостей, предоставляемые для классов WPFWPF, используют эту простую модель реализации оболочки. Основные сложности обработки свойств зависимостей определяются наследуемым поведением системы свойств или реализацией через другие понятия, такие как приведение или обратные вызовы изменения свойства через метаданные свойства.All existing public dependency properties that are provided on the WPFWPF classes use this simple wrapper implementation model; most of the complexity of how dependency properties work is either inherently a behavior of the property system, or is implemented through other concepts such as coercion or property change callbacks through property metadata.


public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
  "AquariumGraphic",
  typeof(Uri),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(null,
      FrameworkPropertyMetadataOptions.AffectsRender, 
      new PropertyChangedCallback(OnUriChanged)
  )
);
public Uri AquariumGraphic
{
  get { return (Uri)GetValue(AquariumGraphicProperty); }
  set { SetValue(AquariumGraphicProperty, value); }
}

Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = DependencyProperty.Register("AquariumGraphic", GetType(Uri), GetType(AquariumObject), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf OnUriChanged)))
Public Property AquariumGraphic() As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set(ByVal value As Uri)
        SetValue(AquariumGraphicProperty, value)
    End Set
End Property

Опять же, по соглашению имя свойства оболочки должно совпадать с именем, выбранным и заданным в качестве первого параметра вызова Register, который зарегистрировал свойство.Again, by convention, the name of the wrapper property must be the same as the name chosen and given as first parameter of the Register call that registered the property. Если свойство не следует соглашению, это не обязательно ведет к его неработоспособности, однако будет наблюдаться несколько серьезных проблем.If your property does not follow the convention, this does not necessarily disable all possible uses, but you will encounter several notable issues:

  • Не будут работать определенные аспекты стилей и шаблонов.Certain aspects of styles and templates will not work.

  • Большинство инструментов и конструкторов полагается на соглашения об именовании для правильной сериализации XAMLXAML, а также для предоставления помощи разработчику на уровне свойств.Most tools and designers must rely on the naming conventions to properly serialize XAMLXAML, or to provide designer environment assistance at a per-property level.

  • Текущая реализация загрузчика WPFWPF XAMLXAML полностью обходит оболочки и основывается на соглашении об именовании при обработке значений атрибутов.The current implementation of the WPFWPF XAMLXAML loader bypasses the wrappers entirely, and relies on the naming convention when processing attribute values. Дополнительные сведения см. в разделе Загрузка кода XAML и свойства зависимостей.For more information, see XAML Loading and Dependency Properties.

Метаданные свойства для нового свойства зависимостейProperty Metadata for a New Dependency Property

При регистрации свойства зависимостей через систему свойств создается объект метаданных, который хранит характеристики свойства.When you register a dependency property, the registration through the property system creates a metadata object that stores property characteristics. Многие из этих характеристик имеют значения по умолчанию, которые задаются, если свойство зарегистрировано с помощью простых подписей Register.Many of these characteristics have defaults that are set if the property is registered with the simple signatures of Register. Другие сигнатуры Register позволяют указать метаданные, которые будут использоваться при регистрации свойства.Other signatures of Register allow you to specify the metadata that you want as you register the property. Как правило, метаданные, задаваемые для свойства зависимостей, предполагают предоставление значений по умолчанию, применяемых для новых экземпляров, которые используют свойство.The most common metadata given for dependency properties is to give them a default value that is applied on new instances that use the property.

При создании свойства зависимостей, существующего в производном классе FrameworkElement, можно использовать более специализированный класс метаданных FrameworkPropertyMetadata, а не базовый класс PropertyMetadata.If you are creating a dependency property that exists on a derived class of FrameworkElement, you can use the more specialized metadata class FrameworkPropertyMetadata rather than the base PropertyMetadata class. Конструктор для класса FrameworkPropertyMetadata имеет несколько сигнатур, где можно задать различные характеристики метаданных в сочетании.The constructor for the FrameworkPropertyMetadata class has several signatures where you can specify various metadata characteristics in combination. Если необходимо указать только значение по умолчанию, используйте сигнатуру, которая принимает один параметр типа Object.If you want to specify the default value only, use the signature that takes a single parameter of type Object. Передайте этот параметр объекта в качестве значения по умолчанию для свойства (указанное значение по умолчанию должно быть типом, который вы указали в качестве параметра propertyType в вызове Register).Pass that object parameter as a type-specific default value for your property (the default value provided must be the type you provided as the propertyType parameter in the Register call).

Для FrameworkPropertyMetadataтакже можно указать флаги параметров метаданных для свойства.For FrameworkPropertyMetadata, you can also specify metadata option flags for your property. Эти флаги преобразуются в дискретные свойства в метаданных свойства после регистрации и используются для передачи определенных условных объектов в другие процессы, например в обработчик макетов.These flags are converted into discrete properties on the property metadata after registration and are used to communicate certain conditionals to other processes such as the layout engine.

Задание соответствующих флагов метаданныхSetting Appropriate Metadata Flags

  • Если свойство (или изменение его значения) влияет на пользовательский интерфейсuser interface (UI), а в частности влияет на то, как система макета должна масштабировать или визуализировать элемент на странице, установите один или несколько следующих флагов: AffectsMeasure, AffectsArrange, AffectsRender.If your property (or changes in its value) affects the пользовательский интерфейсuser interface (UI), and in particular affects how the layout system should size or render your element in a page, set one or more of the following flags: AffectsMeasure, AffectsArrange, AffectsRender.

    • AffectsMeasure указывает, что изменение этого свойства требует изменения ИПUI отрисовки, где содержащий объект может потребовать больше или меньше места в пределах родителя.AffectsMeasure indicates that a change to this property requires a change to ИПUI rendering where the containing object might require more or less space within the parent. Например, этот флаг следует задать для свойства "Ширина".For example, a "Width" property should have this flag set.

    • AffectsArrange указывает, что изменение этого свойства требует изменения ИПUI отрисовку, которая обычно не требует изменения в выделенном пространстве, но указывает на то, что положение в пространстве изменилось.AffectsArrange indicates that a change to this property requires a change to ИПUI rendering that typically does not require a change in the dedicated space, but does indicate that the positioning within the space has changed. Например, этот флаг следует задать для свойства "Выравнивание".For example, an "Alignment" property should have this flag set.

    • AffectsRender указывает, что произошло другое изменение, которое не повлияет на макет и меру, но требует другого рендеринга.AffectsRender indicates that some other change has occurred that will not affect layout and measure, but does require another render. Примером будет свойство, изменяющее цвет существующего элемента, например "Фон".An example would be a property that changes a color of an existing element, such as "Background".

    • Эти флаги часто используются в качестве протокола в метаданных для собственных реализаций переопределения системы свойств или обратных вызовов макета.These flags are often used as a protocol in metadata for your own override implementations of property system or layout callbacks. Например, может существовать обратный вызов OnPropertyChanged, который будет вызывать InvalidateArrange, если какое-либо свойство экземпляра сообщает об изменении значения и имеет AffectsArrange как true в метаданных.For instance, you might have an OnPropertyChanged callback that will call InvalidateArrange if any property of the instance reports a value change and has AffectsArrange as true in its metadata.

  • Некоторые свойства могут влиять на характеристики отрисовки содержащего их родительского элемента указанными выше способами и помимо изменений в обязательном размере, упомянутых выше.Some properties may affect the rendering characteristics of the containing parent element, in ways above and beyond the changes in required size mentioned above. Примером является свойство MinOrphanLines, используемое в модели документов нефиксированного формата, при котором изменения этого свойства могут изменить общую отрисовку документа нефиксированного формата, содержащего абзац.An example is the MinOrphanLines property used in the flow document model, where changes to that property can change the overall rendering of the flow document that contains the paragraph. Используйте AffectsParentArrange или AffectsParentMeasure для обнаружения похожих вариантов в собственных свойствах.Use AffectsParentArrange or AffectsParentMeasure to identify similar cases in your own properties.

  • По умолчанию свойства зависимостей поддерживают привязку данных.By default, dependency properties support data binding. Вы можете специально отключить привязку данных для случаев, когда отсутствует практический смысл в привязке данных или когда быстродействие в привязке данных для больших объектов становится проблемой.You can deliberately disable data binding, for cases where there is no realistic scenario for data binding, or where performance in data binding for a large object is recognized as a problem.

  • По умолчанию Mode привязки данных для свойств зависимостей по умолчанию имеет значение OneWay.By default, data binding Mode for dependency properties defaults to OneWay. Всегда можно изменить привязку на TwoWay для каждого экземпляра привязки; Дополнительные сведения см. в разделе Указание направления привязки.You can always change the binding to be TwoWay per binding instance; for details, see Specify the Direction of the Binding. Но в качестве автора свойства зависимости можно сделать так, чтобы свойство использовало TwoWay режим привязки по умолчанию.But as the dependency property author, you can choose to make the property use TwoWay binding mode by default. Примером существующего свойства зависимости является MenuItem.IsSubmenuOpen. сценарий для этого свойства заключается в том, что логика настройки IsSubmenuOpen и компоновка MenuItem взаимодействуют с стилем темы по умолчанию.An example of an existing dependency property is MenuItem.IsSubmenuOpen; the scenario for this property is that the IsSubmenuOpen setting logic and the compositing of MenuItem interact with the default theme style. Логика свойств IsSubmenuOpen использует привязку данных изначально для поддержания состояния свойства в соответствии с другими свойствами состояния и вызовами методов.The IsSubmenuOpen property logic uses data binding natively to maintain the state of the property in accordance to other state properties and method calls. Еще одним примером свойства, которое привязывает TwoWay по умолчанию, является TextBox.Text.Another example property that binds TwoWay by default is TextBox.Text.

  • Можно также включить наследование свойств в пользовательском свойстве зависимости, установив флаг Inherits.You can also enable property inheritance in a custom dependency property by setting the Inherits flag. Наследование свойств удобно для ситуации, когда родительские и дочерние элементы имеют общее свойство и для дочерних элементов имеет смысл задать то же значение свойства, что и в родительском элементе.Property inheritance is useful for a scenario where parent elements and child elements have a property in common, and it makes sense for the child elements to have that particular property value set to the same value as the parent set it. Примером наследуемого свойства является DataContext, который используется для операций привязки, чтобы включить важный сценарий «основной/подробности» для представления данных.An example inheritable property is DataContext, which is used for binding operations to enable the important master-detail scenario for data presentation. Сделав DataContext наследуемым, все дочерние элементы также наследуют этот контекст данных.By making DataContext inheritable, any child elements inherit that data context also. Благодаря наследованию значения свойства вы можете указать контекст данных в корне приложения или страницы и вам не потребуется уточнять его для привязок во всех возможных дочерних элементах.Because of property value inheritance, you can specify a data context at the page or application root, and do not need to respecify it for bindings in all possible child elements. DataContext также является хорошим примером того, чтобы проиллюстрировать, что наследование переопределяет значение по умолчанию, но оно всегда может быть задано локально для любого дочернего элемента. Дополнительные сведения см. в разделе Использование шаблона "основной/подробности" с иерархическими данными.DataContext is also a good example to illustrate that inheritance overrides the default value, but it can always be set locally on any particular child element; for details, see Use the Master-Detail Pattern with Hierarchical Data. Наследование значения свойства может влиять на производительность, и таким образом, его следует использовать с осторожностью. Дополнительные сведения см. в разделе Наследование значения свойства.Property value inheritance does have a possible performance cost, and thus should be used sparingly; for details, see Property Value Inheritance.

  • Установите флаг Journal, чтобы указать, должно ли свойство зависимостей обнаруживаться или использоваться службами ведения журнала навигации.Set the Journal flag to indicate if your dependency property should be detected or used by navigation journaling services. Примером может быть свойство SelectedIndex. любой элемент, выбранный в элементе управления Selection, должен быть сохранен при переходе к журналу ведения журнала.An example is the SelectedIndex property; any item selected in a selection control should be persisted when the journaling history is navigated.

Свойства зависимости "только для чтения"Read-Only Dependency Properties

Можно определить свойство зависимости, которое доступно только для чтения.You can define a dependency property that is read-only. Однако ситуации для такого использования немного отличаются, как и процедура регистрации свойства в системе свойств и предоставление идентификатора.However, the scenarios for why you might define your property as read-only are somewhat different, as is the procedure for registering them with the property system and exposing the identifier. Дополнительные сведения см. в разделе Свойства зависимостей "только для чтения".For more information, see Read-Only Dependency Properties.

Свойства зависимостей типа коллекцияCollection-Type Dependency Properties

Свойства зависимостей типа коллекции имеют некоторые дополнительные проблемы при реализации, которые необходимо учитывать.Collection-type dependency properties have some additional implementation issues to consider. Подробности см. в разделе Свойства зависимостей типа коллекции.For details, see Collection-Type Dependency Properties.

Замечания по безопасности свойств зависимостейDependency Property Security Considerations

Свойства зависимостей должны объявляться как открытые свойства.Dependency properties should be declared as public properties. Поля идентификаторов свойств зависимостей должны объявляться как открытые статические поля.Dependency property identifier fields should be declared as public static fields. Даже при попытке объявить другие уровни доступа (например, защищенные) доступ к свойству зависимостей всегда можно получить с помощью идентификатора в сочетании с API системы свойств.Even if you attempt to declare other access levels (such as protected), a dependency property can always be accessed through the identifier in combination with the property system APIs. Даже поле защищенного идентификатора потенциально доступно из-за создания отчетов метаданных или API-интерфейсов определения значений, которые являются частью системы свойств, например LocalValueEnumerator.Even a protected identifier field is potentially accessible because of metadata reporting or value determination APIs that are part of the property system, such as LocalValueEnumerator. Дополнительные сведения см. в разделе Безопасность свойств зависимостей.For more information, see Dependency Property Security.

Свойства зависимостей и конструкторы классаDependency Properties and Class Constructors

Есть общий принцип в программировании управляемого кода (он часто принудительно применяется средствами анализа кода, такими как FxCop), подразумевающий, что конструкторы класса не должны вызывать виртуальные методы.There is a general principle in managed code programming (often enforced by code analysis tools such as FxCop) that class constructors should not call virtual methods. Этот принцип обусловлен тем, что конструкторы могут быть вызваны в качестве базовой инициализации конструктора производного класса, а ввод виртуального метода через конструктор может произойти в состоянии неполной инициализации конструируемого экземпляра объекта.This is because constructors can be called as base initialization of a derived class constructor, and entering the virtual method through the constructor might occur at an incomplete initialization state of the object instance being constructed. При наследовании от любого класса, который уже является производным от DependencyObject, следует иметь в виду, что сама система свойств вызывает и предоставляет виртуальные методы внутренним образом.When you derive from any class that already derives from DependencyObject, you should be aware that the property system itself calls and exposes virtual methods internally. Эти виртуальные методы являются частью служб системы свойств WPFWPF.These virtual methods are part of the WPFWPF property system services. Переопределение методов позволяет производным классам участвовать в определении значения.Overriding the methods enables derived classes to participate in value determination. Чтобы избежать потенциальных проблем при инициализации среды выполнения, не задавайте значения свойств зависимостей в конструкторах классов (если только вы не следуете конкретному шаблону конструктора).To avoid potential issues with runtime initialization, you should not set dependency property values within constructors of classes, unless you follow a very specific constructor pattern. Подробнее см. в разделе Шаблоны безопасного конструктора для DependencyObjects.For details, see Safe Constructor Patterns for DependencyObjects.

См. такжеSee also