Демистифицирующие свойства зависимостей - PullRequest
18 голосов
/ 03 декабря 2010

Я много читал о свойствах зависимостей на SO и других сайтах.Но, действительно, не нашел хорошего объяснения и все еще в замешательстве.Я использую как SL, так и WPF.Отличаются ли они в SL и WPF с точки зрения реализации?Почему они нам действительно нужны?Являются ли они статичными, означает, что их значения являются общими?Почему MS ввела свойства зависимостей?

Bounty: Я ищу более полный и полный ответ.

Ответы [ 7 ]

19 голосов
/ 04 декабря 2010

Ответ заключается в самом названии, хотя слово «зависимость» настолько чревато смыслом в разработке программного обеспечения, что не совсем понятно, что это значит.

Свойство зависимости - это свойство одного объекта, чьезначение зависит от некоторых других объектов.Так, например:

  • Значение свойства FontFamily TextBox может (и обычно так) зависит от свойства FontFamily его контейнера.При изменении свойства контейнера значение TextBox изменится.

  • Значение свойства Text TextBox может зависеть от привязанного источника данных,При изменении значения связанного свойства значение свойства Text изменяется.

  • Значение свойства Opacity для Label может зависеть от раскадровки анимациив обычном сценарии, в котором вы настроили элемент пользовательского интерфейса для постепенного или постепенного исчезновения в ответ на какое-либо событие.

  • Значение всех видов свойств любого элемента пользовательского интерфейса можетзависит от стиля, который вы к ним применили.

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

Когда TextBox или объекту, который его отображает, необходимо знать, что это за FontFamily, FontFamily getter вызывает метод GetValue.Этот метод находит значение из контейнера, или анимации, или привязки, или чего-то еще.

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

Если вы посмотрите на реализацию свойств зависимостей, это то, что вы найдете.У объекта зависимости есть словарь, который может содержать или не содержать запись для данного свойства.Метод GetValue получает значения из этого словаря (то есть, как объекты со свойствами зависимости могут иметь локальные значения, которые переопределяют то, от чего они наследуются), и если он не находит значение, он использует метаинформацию о свойстве длявыясните, где он должен выглядеть.

Поскольку эта метаинформация одинакова для каждого объекта в классе (т. е. TextBox.Text работает одинаково для каждого TextBox), словарь, в котором он хранится, является статическим свойствомкласса.

Поэтому, когда вы видите код, подобный следующему:

static Button()
{
   // Register the property
   Button.IsDefaultProperty = 
     DependencyProperty.Register("IsDefault",
     typeof(bool), typeof(Button),
     new FrameworkPropertyMetadata(false,
        new PropertyChangedCallback(OnIsDefaultChanged)));
}

, то происходит то, что метаинформация, определяющая свойство IsDefault для всех объектов Button, добавляется вэтот словарь.И когда вы видите это:

public bool IsDefault
{
  get { return (bool)GetValue(Button.IsDefaultProperty); }
  set { SetValue(Button.IsDefaultProperty, value); }
}

то, что вы видите, - это метод getter, который ищет значение свойства (из локального словаря, родительского объекта или чего-либо еще) на основе этой метаинформации.

Помните, как я сказал, что первое место, которое ищет геттер, чтобы найти значение свойства, находится в локальном словаре объекта?Метод SetValue в установщике - это то, как эта запись добавляется в словарь (если он когда-либо вызывается, то будет, только если вы переопределите зависимость, явно установив свойство, то есть говоря: «Я хочу это TextBox»для отображения текста в Consolas независимо от того, что используют другие элементы управления в окне. ").

Чрезвычайно значительное преимущество, которое мы получаем от такого рода очевидно сложной системы, состоит в том, что свойства зависимостей от объектов только потребляют память, если они установлены. Если я создаю 10 000 TextBox элементов управления и добавляю их к Window, ни один из них на самом деле не содержит ссылку на FontFamily объект. Это 10000 ссылок на объекты, для которых я не выделяю память, и что сборщик мусора не проверяет. На самом деле, если TextBox имеет 100 свойств зависимостей (и он имеет примерно), то всякий раз, когда вы создаете TextBox, это 100 вспомогательных полей, для которых вы не выделяете память. Свойства зависимостей потребляют память только в том случае, если вы их явно указали. Поскольку подавляющее большинство свойств объектов пользовательского интерфейса никогда не устанавливается явно, это фантастическая экономия.

11 голосов
/ 03 декабря 2010

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

  1. Существовозможность добавить значение для свойства, которое не применимо к текущему элементу, но применимо к его дочерним элементам.Например, установка шрифта в контейнере и его каскадное переключение на любые содержащиеся текстовые элементы.
  2. Стоимость с точки зрения размера для неиспользуемых свойств.Взяв приведенный выше пример шрифта ... На правильно оформленной странице их шрифт будет изменен только для нескольких элементов - скорее всего, для нескольких контейнеров верхнего уровня.Если бы мы хранили Font как обычное свойство C #, каждому объекту понадобился бы 32/64-битный указатель на объект шрифта, большинство из которых были бы нулевыми или имели значение по умолчанию.Увеличьте его на количество свойств XAML и типичное количество элементов на странице, и в итоге вам понадобится огромное количество места для хранения ничего или значений по умолчанию.Сравните это со свойствами зависимостей, где значения занимают место, только если они установлены.(Я не смотрел на внутреннюю реализацию, но я представляю, что GetValue (propName) и SetValue (propName) хранят значения в некоторой хеш-таблице для каждого объекта / объекта.)

Было бы неплохо, если бы Microsoft предоставил более приятный синтаксис для создания новых свойств зависимостей, скрывая повторяющийся код с помощью магии компилятора, так же как и для итераторов.Может быть, в C # 6 ...:)

4 голосов
/ 03 декабря 2010
  1. Отличаются ли они в SL и WPF?
    Нет

  2. Почему они нам действительно нужны?
    Короткий ответ: они нужны нам для привязки и оформления данных, и поэтому они были добавлены MS.

  3. Являются ли они статическими, что их значения являются общими?
    Статическая часть - это имя свойства, поэтому его можно получить с помощью GetValue (propName) и установить с помощью SetValue (propName, value)

3 голосов
/ 03 декабря 2010

WPF разработан на основе архитектуры свойств и требует очень мощную систему свойств, поддерживающую -

  1. Различные поставщики для его значения, то есть его значение может быть изменено во время выполнения различными поставщиками, такими как триггеры, стили, анимация, темы и т. Д. (Приоритет значения свойства зависимости)
  2. XAML (поддержка выражений).
  3. Память эффективна (их статическая природа).
  4. Уведомления об изменениях
  5. Значение свойства наследования (Прикрепленные свойства).

статей, которые я нашел очень полезными -

Обзор свойств зависимостей в WPF: http://joshsmithonwpf.wordpress.com/2007/06/22/overview-of-dependency-properties-in-wpf/

Свойства внутренней зависимости: http://www.i -programmer.info / программирования / WPF-разработка / 443-внутри-зависимости свойство-.html

WPF: статическая природа зависимости Свойства: http://dotnetslackers.com/Debugger/re-126399_WPF_The_Static_Nature_of_Dependency_Properties.aspx

3 голосов
/ 03 декабря 2010

Посмотрите Обзор свойств зависимостей на MSDN (или Silverlight версия ).

(Silverlight / WPF) предоставляет набор служб, которые можно использовать для расширения функциональности свойства CLR. В совокупности эти службы обычно называются системой свойств (Silverlight / WPF). Свойство, которое поддерживается системой свойств (Silverlight / WPF), называется свойством зависимости.

Различия между системами свойств Silverlight и WPF см. здесь .

Вот несколько причин, по которым система свойств зависимостей и соединение свойства с системой типов Silverlight / WPF важны:

  • Позволяет задать свойство в стиле
  • Позволяет свойству поддерживать привязку данных
  • Позволяет анимируемому свойству
  • Позволяет свойствам пользовательского элемента управления получать поддержку конструктора в Visual Studio

Обратите внимание, что свойство Dependency обычно поддерживается свойством CLR, что означает, что вы можете взаимодействовать с ним в коде так же, как со свойством CLR.

2 голосов
/ 03 декабря 2010

На большинство поставленных вами вопросов ответили другие, но я дам вам простое объяснение.

Во-первых, они отличаются между Silverlight и WPF, так как свойства зависимостей WPF имеют больше возможностей. Однако, исключая эти дополнительные возможности в WPF, они в основном одинаковы.

Большой вопрос - «когда», если вы их используете («почему» в большинстве случаев уже дан ответ). По сути, они нужны вам, когда вам нужно назначить им расширение разметки в XAML (например, выражение привязки), которое затем будет разрешено / оценено во время выполнения. В большинстве случаев это будет необходимо только при написании пользовательских элементов управления, предоставляющих свойства.

т.е. Перетащите пользовательский элемент управления на поверхность в XAML и назначьте выражение привязки для одного из его свойств.

Я вижу, что некоторые люди используют их повсюду, думая, что они необходимы при разработке Silverlight / WPF, но это не так. У разных людей разные линии, которые они рисуют на песке, но я говорю, что используйте их только тогда, когда это необходимо - что почти 100% времени находится в пределах пользовательских элементов управления.

Явное самореклама: более глубокое (специфичное для Silverlight) обсуждение этой темы в главе 10 моей книги Профессиональные бизнес-приложения в Silverlight 4 .

1 голос
/ 03 декабря 2010

Чтобы добавить к тому, что уже было рассмотрено в других ответах:

Концептуально в своей основе Свойства зависимости - это система, которая позволяет запрашивать получение значения на основе списка различных источников, а не возвращать одно сохраненное значение. В этом есть много разветвлений, перечисленных во многих других ответах, но то, что происходит на самом деле, приводит к чему-то, что ведет себя следующим образом при получении значения (конечно, значительно упрощенного):

private string _coerced;
private string _animated;
private string _local;
private string _triggered;
private string _styled;
private string _inherited;
private string _default;

public string MyDP
{
    get
    {
        return _coerced ?? _animated ?? _local ?? _triggered ?? _styled ?? _inherited ?? _default;
    }
}
...