среда, 23 февраля 2011 г.

Ликбез. Свойства зависимостей (DependencyProperty).

Свойства зависимостей являются совершенно новым воплощением свойств. Без них невозможно работать с основными средствами 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();
}

Приоритезация

Следующей особенностью является динамическое разрешение значений. Это значит что при получении значения из свойства, будет учтено несколько факторов. Например, некоторое значение должно попадать в заданном промежутке между минимальным и максимальным и при необходимости может быть автоматически исправлено в методе Приведения. Т.е. данное свойство зависит от множества поставщиков значений, который имеет свой уровень приоритета. Наивысший приоритет имеет анимация, а самый низкий – значение по умолчанию.
  1. Анимации. Для достижения желаемого эффекта, анимация должна иметь возможность затереть базовое (не анимированное) значение, даже если значение установлено локально.
  2. Локальное значение. Локальные значения присваивается через модель свойств CLR, что приравнивается к присваиванию значения атрибуту в XAML. К данному уровню приоритета относится позднее связывание или ресурсы.
  3. Свойства шаблонов. Значения свойств шаблона, если элемент был создан как часть шаблона.(ControlTemplate или DataTemplate).
  4. Стили. Значения, которые присваиваются при помощи механизма Setter.
  5. Значение по умолчанию. Значение, которое было присвоено свойству при его регистрации.

Наследование поведения

Наследование поведения – это механизм, при котором значения свойств родителя наследуют дочерние элементы. Данным поведением обладает свойство 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));
Таким образом, элемент получает свойство «задаром».

Вместо заключения

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

понедельник, 7 февраля 2011 г.

iOS Silverlight ListControl

Не так давно закончил еще один интересный компонент из списка iOS :)
Данный компонент предназначен для прокрутки длинных списков. "Прибить" можно любые данные и описать их с помощью соответствующих шаблонов. Компонент еще "сырой", есть ошибки, поэтому используйте на свой страх и риск.
Пример с двумя вариантами использования ниже.


IPhone toggle button
 
Исходный код можно слить отсюда

Newer Posts Older Posts