Свойства зависимости

66

Подобно любому API-интерфейсу .NET, внутри реализации WPF используются все члены системы типов .NET (классы, структуры, интерфейсы, делегаты, перечисления) и каждый член типа (свойства, методы, события, константные данные, поля только для чтения и т.п.). Однако WPF также поддерживает уникальную программную концепцию под названием свойства зависимости (dependency property).

Свойства зависимости являются совершенно новой, значительно более полезной, реализацией свойств. Без них вы не сможете работать с основными средствами WPF, такими как анимация, привязка данных и стили.

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

И все же свойства зависимости не являются обычными свойствами. Лучше всего представлять себе эти свойства как обычные (определяемые в .NET обычным образом), но с дополнительным набором возможностей WPF. В концептуальном отношении поведение свойств зависимости не отличается от поведения обычных свойств, однако реализованы они по-другому. Причина проста: производительность. Если бы разработчики WPF просто внесли дополнительные возможности в систему свойств .NET, то им пришлось бы создать сложный и громоздкий слой для вашего кода. Рядовые свойства не могут поддерживать все характеристики свойств зависимости, не перегружая при этом систему.

Свойства зависимости являются специфическим детищем WPF. Однако в библиотеках WPF они всегда заключены в оболочки обычных процедур свойств .NET. Это позволяет использовать их обычным образом даже в том коде, который не имеет понятия о системе свойств зависимости WPF. На первый взгляд странно, что новая технология упакована в старую, однако только так WPF может изменить такой фундаментальный ингредиент, как свойства, не нарушая структуру остального мира .NET.

Подобно "нормальному" свойству .NET (которое в литературе, посвященной WPF, часто называют свойством CLR (CLR property)), свойства зависимости могут устанавливаться декларативно, с использованием XAML или программно в файле кода. Более того, свойства зависимости (подобно свойствам CLR) в конечном итоге предназначены для инкапсуляции полей данных класса и могут быть сконфигурированы как доступные только для чтения, только для записи или для чтения и записи.

Что более интересно: почти в любом случае вы будете пребывать в счастливом неведении относительно того, что на самом деле устанавливаете (или читаете) свойство зависимости, а не свойство CLR! Например, свойства Height и Width, которые элементы управления WPF наследуют от FrameworkElement, а также член Content, унаследованный от ControlContent — все это фактически свойства зависимости:

<!-- Установить три свойства зависимости -->
<Button х:Name = "btnMyButton" Height = "50" Width = "100" Content = "OK"/>

С учетом всех этих сходств возникает вопрос: зачем нужно было определять в WPF новый термин для такой знакомой концепции? Причина кроется в способе реализации свойства зависимости внутри класса. На высшем уровне все свойства зависимости создаются следующим образом:

Будучи реализованными, свойства зависимости представляют множество мощных средств, используемых различными технологиями WPF, включая привязку данных, службы анимации, стили и т.д. В основе своей мотивация свойств зависимости заключается в предоставлении способа вычисления значения свойства на основе значений других источников. Ниже приведен список некоторых основных преимуществ, которые выходят за рамки простой инкапсуляции данных, имеющейся в свойстве CLR:

Запомните, что во многих случаях вы будете взаимодействовать с существующим свойством зависимости в манере, идентичной нормальному свойству CLR (благодаря оболочке XAML).

Пройди тесты
Лучший чат для C# программистов