Когда использовать свойства зависимостей

Иногда мне кажется, что я использую свойства зависимостей без надобности. Когда мне нужно его использовать? Когда у меня есть собственность, которая зависит от других свойств? Скажем, у меня есть свойство Color, и я хочу, чтобы оно зависело от свойств Hue, Saturation, Luminosity. Использовать ли свойство зависимости? Или что я использую? Я контролирую, что привязано к Color для обновления при изменении свойств Hue, Saturation, Luminosity.

на данный момент то, что я сделал, было

public byte Hue {
    get { return _hue; }
    set
    {
        if (_hue == value)
            return;
        _hue = value;
        NotifyPropertyChanged("Hue");
        NotifyPropertyChanged("Color"); // to update controls bound to color
    }
}

Но я думаю, что это неправильный способ делать что-то? Если у меня будет больше свойств, влияющих на цвет, у меня будет одна дополнительная строка во всех этих свойствах?


person Jiew Meng    schedule 05.11.2010    source источник
comment
Я не думаю, что это неоправданные накладные расходы с точки зрения кода, и это определенно легче, чем добавление DependencyProperty.   -  person Dan Puzey    schedule 05.11.2010
comment
если вы идете по маршруту hsl-color. Я бы сделал это, чтобы мне не приходилось так часто вычислять. Например, всегда сохраняйте H, S и L и конвертируйте только тогда, когда им нужно синхронизироваться. Это значительно улучшит вашу скорость.   -  person Lee Louviere    schedule 11.06.2012


Ответы (5)


Вы должны использовать DependencyProperty только тогда, когда хотите иметь возможность привязать его значение к чему-либо через XAML, например

<local:MyObject MyDependencyProperty="{Binding ...}" />

Обновление: как упомянуто Яном ниже, свойства зависимостей также необходимы, если вы хотите иметь возможность анимировать свое свойство или установить его с помощью стиля

Если вам не нужно работать таким образом, то в этом нет необходимости. например Если вы просто хотите установить значение константы через XAML (как показано ниже), это будет работать без использования DependencyProperty

<local:MyObject MyRegularProperty="Some Value" />

Аналогичным образом, если вы хотите привязать к к значению свойства (например) вашей модели представления:

<TextBlock Text="{Binding MyViewModelProperty}" />

тогда вам не нужно использовать DependencyProperty. Если вы реализуете INotifyPropertyChanged, то Text все равно будет обновляться при изменении свойства.

Изменить: перечитав ваш вопрос, я не уверен, повлияет ли на вашу ситуацию то, используете ли вы DependencyProperty - если я правильно его прочитал, все, что вы хотите сделать вызывает обновление ряда свойств в пользовательском интерфейсе при изменении любого из этих свойств, верно?

Я не думаю, что есть что-то неправильное в том, как вы реализуете что-то в данный момент (т.е. поднимаете много PropertyChanged событий в каждом сеттере), но если вам это не нравится, вы можете попробовать иметь одно свойство, которое предоставляет все соответствующие дочерние свойства, к которым нужно привязаться, рассчитываются:

class ColorWrapper
{
    public Color Color  { get; set; }
    public byte Hue
    {
        get { return this.Color.Hue; } //or however this is calculated
}

Затем создайте свойство Color в вашей ViewModel, которое вызывает событие PropertyChanged и связывает его через View:

<TextBlock Text="{Binding Color.Hue}" />

Как я уже сказал, я бы не сказал, что это особенное улучшение по сравнению с тем, что у вас уже есть.

person Steve Greatrex    schedule 05.11.2010
comment
Связывание - не единственный вариант использования. Если объект, реализующий свойство, является элементом пользовательского интерфейса (а некоторые люди реализуют DP на объектах, не относящихся к пользовательскому интерфейсу), система DP включает различные другие функции, включая анимацию, стили и (только WPF - Silverlight не имеет этих) триггеры. Кроме того, DP полезны, если свойство часто остается в его значении по умолчанию, потому что каждый экземпляр использует пространство только для DP, которые были установлены. - person Ian Griffiths; 05.11.2010
comment
@Ian Griffiths, хорошее замечание по анимации и стилю - ответ обновлен. Ваш комментарий о значениях по умолчанию, я полагаю, действителен, но, учитывая накладные расходы, связанные с реализацией и использованием свойства зависимости над простым свойством (особенно, если вы еще не работаете с DependencyObject), я бы обычно не пошел по этому пути. - person Steve Greatrex; 05.11.2010
comment
Значение по умолчанию оказывает нетривиальное влияние на производительность WPF. Это экономит несколько сотен байтов на объект, а если ваше визуальное дерево содержит несколько тысяч объектов, это несколько сотен КБ. Крошечная доля общей памяти, но достаточно, чтобы существенно повлиять на эффективное использование кеш-памяти ЦП (особенно во время макета). Однако это, вероятно, будет неактуальным для любых объектов, не относящихся к пользовательскому интерфейсу, и, вероятно, не будет большим подспорьем для пользовательских элементов пользовательского интерфейса, где высока вероятность, что вы будете устанавливать любые свойства cusom, которые вы определяете. Так что я согласен ... Я просто хотел проиллюстрировать, что DP служат нескольким целям. - person Ian Griffiths; 05.11.2010
comment
Интересно - раньше я не рассматривал аспекты производительности :) - person Steve Greatrex; 05.11.2010

Общие правила таковы:

  • Для элементов управления XAML используйте свойства зависимостей;

  • Для данных (к которым вы привязываетесь в интерфейсе) используйте INotifyPropertyChanged.

Есть исключения, но они редки.

person Pieter van Ginkel    schedule 05.11.2010

Еще одно использование свойств зависимости - это журнал навигации. Настраиваемые свойства зависимостей на странице с флагом Juornal в метаданных включаются в состояние, которое WPF сохраняет для страницы.

person Codeheda    schedule 24.10.2012

Помните, что свойства зависимостей, хотя они допускают привязку либо в качестве источника, либо в качестве цели, также чувствительны к потокам, и при сериализации вам придется использовать суррогат, сериализацию, поскольку DependencyObject не сериализуем.

Да, и Equals и GetHashCode запечатаны :(

person Florian Doyon    schedule 05.11.2010

Еще одно использование DP - это вложенное свойство. Присоединенное свойство - это тип DependencyProperty, в котором свойство можно использовать в любых других элементах управления. Например, вы можете объявить AttachedProperty в классе MyAttachedProperties и использовать его для TextBlock, Button, Label, ...

Некоторые примеры прикрепленных свойств: Grid.Row, Grid.Column. Индивидуальный:

public static readonly DependencyProperty DarkThemeProperty =
    DependencyProperty.RegisterAttached("DarkTheme", typeof(Theme), typeof(Page));
 
public static Theme GetDarkTheme(DependencyObject obj)
{
    return (Theme)obj.GetValue(DarkThemeProperty);
}
 
public static void SetDarkTheme(DependencyObject obj, Theme value)
{
    obj.SetValue(DarkThemeProperty, value);
}
person Daniel B    schedule 06.10.2020