Общие сведения о свойствах зависимости
Windows Presentation Foundation (WPF) предоставляет набор служб, которые могут использоваться для расширения функциональности свойства common language runtime (CLR). Собирательно, эти службы называют системой свойств WPF. Свойство, поддерживаемое системой свойств WPF, называется свойством зависимостей. Этот обзор содержит описание системы свойств WPF и возможностей свойства зависимостей. Он также включает руководство по использованию существующих свойств зависимостей в разметке XAML и в программном коде. Этот раздел также знакомит со специальными аспектами свойств зависимости такими, как метаданные свойства зависимости и способы создания собственного свойства зависимости в настраиваемом классе.
В этом разделе содержатся следующие подразделы.
- Предварительные требования
- Свойства среды CLR и свойства зависимостей
- Свойства зависимости обеспечивают свойства CLR
- Установка значений свойства
- Функциональность свойства, предоставленная свойством зависимости
- Приоритет значения свойств зависимостей
- Дополнительные сведения о свойствах зависимости
- Связанные разделы
Предварительные требования
Чтение этого раздела подразумевает наличие базовых знаний о CLR и об объектно-ориентированном программировании. Чтобы выполнить примеры в этом подразделе, следует также понимать принципы работы XAML и знать, как создаются приложения WPF. Дополнительные сведения см. в разделе Пошаговое руководство. Начало работы с WPF.
Свойства среды CLR и свойства зависимостей
В WPF свойства обычно предоставляются как свойства common language runtime (CLR). На базовом уровне можно напрямую взаимодействовать с этими свойствами и не знать, что они реализованы в виде свойства зависимостей. Однако следует более близко ознакомиться с некоторыми или со всеми компонентами системы свойств WPF, чтобы можно было использовать их преимущества.
Целью свойств зависимости является предоставление способа для вычисления значения свойства на основе значений других входных данных. Эти другие входные данные могут включать свойства системы, такие как темы и пользовательские параметры, механизмы определения свойства по требованию, например, привязка данных и анимации/раскадровки, многократное использование шаблонов, например, ресурсов и стилей, или значения, известные через связи типа родитель-потомок с другими элементами в дереве элементов. Кроме того, свойство зависимости может быть реализовано для обеспечения независимой проверки, значений по умолчанию, обратных вызовов, следящих за изменениями других свойств, и системы, удерживающей значения свойства на основе информации потенциальной исполняющей среды. Производные классы могут изменить некоторые специфические характеристики существующего свойства с помощью переопределения метаданных свойства зависимости скорее, чем переопределения фактической реализации существующих свойств или создания новых свойств.
В справочнике SDK можно определить, какое свойство является свойством зависимости по наличию раздела "Сведения о свойстве зависимости" на странице управляемой ссылки для этого свойства. Раздел "Сведения о свойстве зависимости" включает ссылку на идентификатор поля DependencyProperty для этого свойства зависимости, а также включает список параметров метаданных, установленных для этого свойства, информацию по переопределению каждого класса и другие сведения.
Свойства зависимости обеспечивают свойства CLR
Свойства зависимости и система свойств WPF расширяют функциональность свойства, предоставляя тип, который обеспечивает свойство, в качестве альтернативной реализации для стандартного шаблона обеспечения свойства с помощью закрытого поля. Этот тип называется DependencyProperty. Другом важным типом, определяющим систему свойств WPF, является DependencyObject. DependencyObject определяет базовый класс, который может регистрировать свойство зависимости и быть его владельцем.
Далее даны краткие определения терминов, используемых в этой документации software development kit (SDK) при описании свойств зависимости:
свойство зависимости. Свойство, обеспечиваемое DependencyProperty;
Идентификатор свойства зависимостей. Экземпляр DependencyProperty, который извлекается как возвращаемое значение при регистрации свойства зависимостей и затем хранится в качестве статического члена класса. Этот идентификатор используется в качестве параметра для многих APIs, взаимодействующих с системой свойств WPF;
программа-оболочка среды CLR. Фактические реализации получения и задания свойства. Эти реализации включают идентификатор свойства зависимости, используя его в вызовах GetValue и SetValue, предоставляя таким образом обеспечение для свойства, использующего систему свойств WPF.
В следующем примере определяется свойство зависимости IsSpinning и показывается отношение идентификатора DependencyProperty к обеспечиваемому им свойству.
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning",
GetType(Boolean),
GetType(MyCode))
Public Property IsSpinning() As Boolean
Get
Return CBool(GetValue(IsSpinningProperty))
End Get
Set(ByVal value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean),
...
);
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
Важным является правило именования свойства и его обеспечивающее поле DependencyProperty. Имя поля всегда является и именем свойства с добавлением суффикса Property. Дополнительные сведения об этом правиле и его основаниях содержатся в разделе Пользовательские свойства зависимостей.
Установка значений свойства
Свойства можно задать либо в программном коде либо в разметке XAML.
Установка значений свойства в XAML
В следующем примере XAML задается красный цвет фона кнопки. В этом примере показана ситуация, в которой в созданном коде строковый параметр для атрибута XAML является типом, преобразуемым средством синтаксического анализа XAML системы WPF в тип WPF (Color в виде объекта SolidColorBrush).
<Button Background="Red" Content="Button!"/>
XAML поддерживает различные формы синтаксиса для задания свойств. Выбор синтаксиса для конкретного свойства будет зависеть как от типа значения, используемого свойством, так и от других факторов, таких как наличие преобразователя типа. Дополнительные сведения об использовании синтаксиса XAML для задания свойств см. в разделах Общие сведения о языке XAML (WPF) и Подробное описание синтаксиса XAML.
В качестве примера безатрибутного синтаксиса в следующем примере XAML задается другой цвет фона кнопки. В этот раз, вместо настройки простой заливки цветом фон задается в виде изображения с помощью элемента, представляющего это изображение, и источника этого изображения, указанного как атрибут вложенного элемента. Это пример синтаксиса элемента свойства.
<Button Content="Button!">
<Button.Background>
<ImageBrush ImageSource="wavy.jpg"/>
</Button.Background>
</Button>
Установка свойств в программном коде
Установка значений свойства зависимости в коде обычно заключается просто в вызове реализации задания свойства, предоставляемого "программой-оболочкой" CLR.
Dim myButton As New Button()
myButton.Width = 200.0
Button myButton = new Button();
myButton.Width = 200.0;
Получение значения свойства также, фактически, является вызовом для реализации получения "программы-оболочки":
Dim whatWidth As Double
whatWidth = myButton.Width
double whatWidth;
whatWidth = myButton.Width;
Также можно непосредственно вызвать систему свойства APIs GetValue и SetValue. Обычно это необязательно при использовании существующих свойств (оболочки наиболее удобны и предоставляют лучшее предоставление свойства для средств разработчика), но непосредственный вызов APIs подходит для определенных случаев.
Свойства можно также установить в XAML, а позднее получить доступ к ним в программном коде через код программной части. Дополнительные сведения см. в разделе Код программной части и XAML в WPF.
Функциональность свойства, предоставленная свойством зависимости
Свойство зависимости обеспечивает функциональность, расширяющую функциональность свойства в отличие от свойства, которое обеспечивается полем. Часто каждый такой набор функций представляет или поддерживает специальную возможность общего набора возможностей WPF:
Ресурсы
привязка данных,
стили,
анимации,
переопределения метаданных,
наследование значения свойства,
интеграция конструктора WPF.
Ресурсы
Значение свойства зависимости может быть задано ссылкой на ресурс. Ресурсы обычно указываются как значения свойства Resources корневого элемента страницы или приложения (эти расположения делают возможным наиболее удобный доступ к ресурсу). В следующем примере показан порядок определения ресурса SolidColorBrush.
<DockPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</DockPanel.Resources>
После того как ресурс определен, на него можно ссылаться и использовать его для предоставления значения свойства:
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
На данный ресурс ссылаются как на Расширение разметки DynamicResource (в XAML WPF можно использовать либо статическую, либо динамическую ссылку на ресурс). Чтобы использовать динамическую ссылку на ресурс, необходимо установить свойство зависимости, поэтому это является специфическим использованием динамической ссылки на ресурс, которое становится возможным благодаря системе свойств WPF. Дополнительные сведения см. в разделе Общие сведения о ресурсах.
Примечание |
---|
Ресурсы рассматриваются как локальное значение. Это означает, что если задать другое локальное значение, то ссылка на ресурс будет удалена.Дополнительные сведения см. в разделе Приоритет значения свойств зависимостей. |
Привязка данных
Свойство зависимости может ссылаться на значение с помощью привязки данных. Привязка данных работает через специальный синтаксис расширения разметки в XAML или объект Binding в программном коде. С помощью привязки данных определение окончательного значения свойства откладывается до времени выполнения, а во время выполнения значение извлекается из источника данных.
В следующем примере показана установка свойства Content для элемента управления Button с помощью привязки, объявленной в XAML. Привязка использует наследуемый контекст данных и источник данных XmlDataProvider (не показано). Привязка сама задает нужное свойство источника с помощью XPath в источнике данных.
<Button Content="{Binding XPath=Team/@TeamName}"/>
Примечание |
---|
Привязки рассматриваются как локальное значение. Это означает, что если задать другое локальное значение, то привязка будет удалена.Дополнительные сведения см. в разделе Приоритет значения свойств зависимостей. |
Свойства зависимости или класс DependencyObject изначально не поддерживают INotifyPropertyChanged для формирования уведомлений об изменениях в значении свойства источника DependencyObject для операций привязки данных. Дополнительных сведения о создании свойств для использования в привязке данных, которые могли бы предоставлять отчет об изменениях в целевой привязке данных, см. в разделе Общие сведения о связывании данных.
Стили
Стили и шаблоны являются двумя главными мотивированными скриптами для использования свойств зависимости. Стили особенно полезны для настройки свойств, определяющих user interface (UI) приложения. Обычно стили определяются в качестве ресурсов в XAML. Стили взаимодействуют с системой свойств, так как они обычно содержат "присвоения" для конкретного свойства, а также "триггеры", которые изменяют значение свойства на основе значения реального времени для другого свойства.
В следующем примере создается очень простой стиль (который будет определяться внутри словаря Resources, не показано), а затем этот стиль применяется непосредственно к свойству Style для элемента управления Button. Присвоение в стиле задает значение "зеленый" свойства Background для элемента управления Button.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
Дополнительные сведения см. в разделе Стилизация и использование шаблонов.
Анимации
Свойства зависимости могут быть анимированными. При применении и выполнении анимации анимированное значение действует с более высоким приоритетом, чем любое значение (например локальное значение), которое свойство имеет в противном случае.
В следующем примере анимируется значение элемента Background в свойстве Button (формально, Background анимируется с использованием синтаксиса элемента свойства для указания пустого SolidColorBrush как Background, затем свойство Color этого элемента SolidColorBrush оказывается непосредственно анимируемым свойством).
<Button>I am animated
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Red" To="Green" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Дополнительные сведения об анимации свойств содержатся в разделах Общие сведения об эффектах анимации и Общие сведения о Storyboard.
Переопределения метаданных
Можно изменять некоторые параметры поведения свойства зависимости с помощью переопределения метаданных для этого свойства при создании производного от класса, изначально регистрирующего свойство зависимости. Переопределение метаданных зависит от идентификатора DependencyProperty. Переопределение метаданных не требует повторной реализации свойства. Изменение метаданных изначально обрабатывается системой свойств; каждый класс потенциально содержит отдельные метаданные для всех свойств, которые наследуются от базовых классов, на основе каждого типа.
В следующем примере метаданные переопределяются для свойства зависимости DefaultStyleKey. Переопределение этих метаданных свойства зависимости является частью шаблона реализации, создающего элементы управления, которые могут использовать стили по умолчанию из темы.
Public Class SpinnerControl
Inherits ItemsControl
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
End Sub
End Class
public class SpinnerControl : ItemsControl
{
static SpinnerControl()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(SpinnerControl),
new FrameworkPropertyMetadata(typeof(SpinnerControl))
);
}
}
Дополнительные сведения о переопределении или получении метаданных свойства содержатся в разделе Метаданные свойства зависимости.
Наследование значения свойства
Элемент может наследовать значения свойства зависимостей от родительского элемента дерева объектов.
Примечание |
---|
Поведение наследования значения свойства доступно не глобально для всех свойств зависимости, поскольку время вычисления наследования оказывает влияние на быстродействие системы.Наследование значения свойства обычно доступно только для свойств, где определенный скрипт предполагает, что наследование свойств значения является подходящим методом.Определить, поддерживает ли свойство зависимостей наследование, можно с помощью раздела Сведения о свойстве зависимостей для этого свойства зависимостей справочнике SDK. |
В следующем примере показана привязка и присвоение значений свойству DataContext, указывающему источник привязки, который не был показан в предыдущем примере привязки. Никакие последующие привязки в дочерних объектах не требуют задания источника, они могу использовать унаследованное значение из объекта DataContext в родительском объекте StackPanel. (Также можно напрямую задать для дочернего объекта собственное значение DataContext или Source в объекте Binding и намеренно не использовать унаследованное значение для контекста данных привязок.)
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}">
<Button Content="{Binding XPath=Team/@TeamName}"/>
</StackPanel>
Дополнительные сведения см. в разделе Наследование значения свойства.
Интеграция конструктора WPF
Пользовательский элемент управления со свойствами, которые реализованы в виде свойств зависимостей, получает соответствующую поддержку Конструктор WPF для Visual Studio. Примером является возможность редактирования прямых и вложенных свойств зависимостей с помощью окна Свойства. Дополнительные сведения см. в разделе Общие сведения о разработке управления.
Приоритет значения свойств зависимостей
Получение значения свойства зависимости означает, что потенциально получено значение, которое было установлено для этого свойства посредством любого из остальных источников входных данных на основе свойств, участвующих в системе свойств WPF. Приоритет значения свойства зависимости осуществляется таким образом, чтобы можно было предсказать взаимодействие различных скриптов для получения свойствами их значений.
Рассмотрим следующий пример. В примере выполняется включение стиля, который применяется для всех кнопок и их свойств Background, затем также указывается одна кнопка с локально заданным значением Background.
Примечание |
---|
Иногда при описании свойств зависимости в документации SDK использует термин "локальное значение" или "локально заданное значение".Локально заданное значение является значением свойства, которое устанавливается непосредственно для экземпляра объекта в программном коде или как атрибут элемента в XAML. |
Фактически, для первой кнопки свойство установлено дважды, но применяется только одно значение с более высоким приоритетом. локально заданное значение имеет наивысший приоритет (за исключением случая выполняемой анимации, но не для анимации, применяемой в этом примере) и, таким образом, для цвета фона первой кнопки используется локально заданное значение вместо значения присваивающего объекта. Вторая кнопка не имеет локального значения (и никаких других значений с более высоким приоритетом, чем стиль, заданный присваивающим объектом) и, таким образом, цвет фона для этой кнопки поступает из стиля присваивающего объекта.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
</Style>
</StackPanel.Resources>
<Button Background="Green">I am NOT red!</Button>
<Button>I am styled red</Button>
</StackPanel>
Обоснования приоритета свойств зависимости
Обычно, нежелательно, чтобы стили применялись всегда и скрывали каждое локально заданное значение отдельного элемента (в противном случае будет очень сложно использовать стили или элементы в общем). Поэтому значения, полученные из стилей, работают с более низким приоритетом, чем локально заданные значения. Более полный список свойств зависимости и расположений, из которых могут поступать действующие значения свойства зависимости, см. в разделе Приоритет значения свойств зависимостей.
Примечание |
---|
Существует ряд свойств, определенных для элементов WPF, которые не являются свойствами зависимости.В целом, свойства были реализованы в виде свойств зависимостей только там, где возникала необходимость поддерживать по крайней мере один из скриптов, реализуемых системой свойств: привязка данных, стили, анимирование, поддержка значений по умолчанию, наследование, вложенные свойства или недействительность. |
Дополнительные сведения о свойствах зависимости
Присоединенное свойство является типом свойства, поддерживающим специализированный синтаксис XAML. Вложенное свойство часто не имеет соответствия 1:1 со свойством common language runtime (CLR) и не обязательно является свойством зависимости. Обычная цель вложенного свойства заключается в разрешении дочерним элементам отправлять отчеты о значении свойств родительским элементам, даже если родительский и дочерний элементы не обладают этим свойством как частью списка элементов класса. Основной скрипт заключается в разрешении дочерним элементам уведомлять родительский элемент о том, как они должны быть представлены в UI; пример содержится в разделе Dock или Left. Дополнительные сведения см. в разделе Общие сведения о вложенных свойствах зависимостей.
Разработчики компонента или разработчики приложения могут пожелать создать собственное свойство зависимости для включения возможностей, таких как привязка данных или поддержка стилей, или для аннулирования и поддержки приведения значения. Дополнительные сведения см. в разделе Пользовательские свойства зависимостей.
Обычно свойства зависимости должны рассматриваться как открытые свойства, доступные или, по крайней мере, видимые любому вызывающему объекту, который имеет доступ к экземпляру. Дополнительные сведения см. в разделе Безопасность свойства зависимости.
См. также
Основные понятия
Пользовательские свойства зависимостей
Свойства зависимости "только для чтения"