Свойства зависимостей являются совершенно новым воплощением свойств. Без них невозможно работать с основными средствами WPF/Silverlight, такими как анимация/раскадровка, привязка данных и стили. В концептуальном отношении поведение свойств зависимостей не отличается от поведения обычных свойств CLR (common language runtime), однако “за кулисами” совершенно иная модель. Причина проста - производительность. Обычные свойства не могут поддержать всех характеристик свойств зависимостей без приличной нагрузки на систему.
В свойствах зависимостей можно выделить несколько ключевых моментов:
Таким образом, элемент получает свойство «задаром».
В свойствах зависимостей можно выделить несколько ключевых моментов:
- Проверка достоверности значений;
- Приоритезация;
- Наследование поведения;
- Совместное использование свойства зависимостей.
Проверка достоверности и коррекция значений
Проверка достоверности значений разделяется на три этапа:- Приведение
- Проверка
- Обратный вызов
Проверка достоверности
При регистрации DP можно указать обратный вызов проверки. Данный метод позволяет произвести проверку, которая обычно добавляется в установочную часть процедуры свойства. Данный метод должен принимать объектный параметр и возвращать булево значение. Данный метод проверки имеет одно ограничение: он является статическим, что не позволяет учесть в проверке состояние объекта. Эту проблему лучше решать с помощью Приведенияpublic static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof (double), typeof (MainWindow),
new FrameworkPropertyMetadata(0), ValidateValueCallback);
private static bool ValidateValueCallback(object value)
{
throw new NotImplementedException();
}
Приведения
Приведения – это действие, которое происходит перед самой проверкой, и позволяет менять значение (обычно для согласования с остальными свойствами) или отклонить изменения (DependencyProperty.UnsetValue)public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof (double), typeof (MainWindow),
new FrameworkPropertyMetadata(0, PropertyChangedCallback, CoerceValueCallback));
private static object CoerceValueCallback(DependencyObject sender, object baseValue)
{
throw new NotImplementedException();
}
Обратный вызов
После того как оба предыдущих метода успешно отработали, начинает действовать обратный вызов, который может поднять событие изменения или среагировать на изменение состояния.public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof (double), typeof (MainWindow),
new FrameworkPropertyMetadata(0, PropertyChangedCallback, CoerceValueCallback));
private static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
throw new NotImplementedException();
}
Приоритезация
Следующей особенностью является динамическое разрешение значений. Это значит что при получении значения из свойства, будет учтено несколько факторов. Например, некоторое значение должно попадать в заданном промежутке между минимальным и максимальным и при необходимости может быть автоматически исправлено в методе Приведения. Т.е. данное свойство зависит от множества поставщиков значений, который имеет свой уровень приоритета. Наивысший приоритет имеет анимация, а самый низкий – значение по умолчанию.- Анимации. Для достижения желаемого эффекта, анимация должна иметь возможность затереть базовое (не анимированное) значение, даже если значение установлено локально.
- Локальное значение. Локальные значения присваивается через модель свойств CLR, что приравнивается к присваиванию значения атрибуту в XAML. К данному уровню приоритета относится позднее связывание или ресурсы.
- Свойства шаблонов. Значения свойств шаблона, если элемент был создан как часть шаблона.(ControlTemplate или DataTemplate).
- Стили. Значения, которые присваиваются при помощи механизма Setter.
- Значение по умолчанию. Значение, которое было присвоено свойству при его регистрации.
Наследование поведения
Наследование поведения – это механизм, при котором значения свойств родителя наследуют дочерние элементы. Данным поведением обладает свойство FontSize или FontFamily. Например, если панели задать размер шрифта 14pt, то всем дочерним элементам на данной панели, будет присвоено значение размера шрифта 14pt. Чтобы заставить это работать, необходимо при регистрации свойства передать экземпляр класса FrameworkPropertyMetadata, в котором необходимо указать одну или несколько установок параметров метаданных (в данном случае FrameworkPropertyMetadataOptions.Inherits).public static readonly DependencyProperty FontSizeProperty =
DependencyProperty.Register("FontSize", typeof (double), typeof (MainWindow),
new FrameworkPropertyMetadata(12,FrameworkPropertyMetadataOptions.Inherits));
Совместное использование свойства зависимостей
Некоторые классы совместно используют одно и то же свойства зависимостей, даже если они имеют резные иерархии классов. Например, TextBlock.FontFamily и Control. FontFamily указывают на одно и то же статическое свойство зависимостей, которое определенно в классе TextElement. В классе TextElement регистрируется свойство, а в классах TextBlock и Control просто повторно используют его посредством вызова метода DependencyProperty.AddOwner():FontSizeProperty = TextElement.FontSizeProperty.AddOwner(typeof (MainWindow));



1 коммент.:
Хм, о совместном использовании dependency property не знал.
Антон, может стоит еще описать Attached Property и их применение в практических примерах? Как думаешь?
Я бы еще подчеркнул, что основная идея dependency property - это все таки dynamic value resolve. Собственно, их название, их "dependency" и состоит в том, что значение, которое они сейчас содержат зависит, от: анимации, локальных значений, привязок, стилей, и т.д.
Отправить комментарий