开发者

When to use Dependency Properties

I sometimes think I maybe using Dependency Properties unnecessarily. When do I need to use it? When I have a property that dependes on other properties? Say I have a Color property that I want it to be dependent on properties Hue, Saturation, Luminosity do I use a dependency property? Or what do I use? I control开发者_如何学Cs thats bound to Color to update when properties Hue, Saturation, Luminosity are changed.

for now what I did was

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

But I think this is not the right way of doing things? If I have more properties that affect color, I will have 1 extra line in all those properties?


You should only use a DependencyProperty when you want to be able to bind its value to something through XAML, e.g.

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

Update: as mentioned by Ian below, dependency properties are also required if you want to be able to animate your property or set it through a style

If you do not need to work in this way then it is unnecessary. e.g. If you just want to be able to set the value to a constant through XAML (as below) this will work without using a DependencyProperty

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

Similarly, if you want to bind to the value of a property on (for example) your view model:

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

then you do not need to use a DependencyProperty. Provided that you implement INotifyPropertyChanged then the Text will still be updated when the property changes.

Edit: on re-reading your question, I am not sure whether or not your situation will be affected by whether or not you use a DependencyProperty - if I'm reading it correctly, all you want to do is cause a number of properties to be updated on the UI when any one of those properties changes, right?

I don't think there is anything wrong with how you are implementing things at the moment (i.e. raising a lot of PropertyChanged events in each setter), but if you aren't keen on in then you could try having a single property that exposes relevant child properties to bind to that are all calculated:

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

Then have a Color property on your ViewModel that raises the PropertyChanged event and bind to that through the View:

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

As I said, I wouldn't say that this is particularly an improvement on what you have already though.


The general rules are:

  • For XAML controls, use dependency properties;

  • For data (which you bind to in the interface), use INotifyPropertyChanged.

There are exceptions, but they are rare.


Another use of dependency properties is with navigation journal. Custom dependency properties on a Page with Juornal flag in the meta-data are included in the state that WPF saves for the page.


Remember that Dependency Properties, although they allow Binding either as a source or a target, are also Thread-Sensitive, and when serializing you will have to use a surrogate, serialization as DependencyObject isn't serializable.

Oh, and Equals and GetHashCode are sealed :(


Another usage of DP is Attached Property. Attached property is a type of DependencyProperty where the property can be used in any other controls. For example, you can declare AttachedProperty in class MyAttachedProperties and used it for TextBlock, Button, Label,...

Some examples of Attached Properties: Grid.Row, Grid.Column. A customized one:

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);
}


I was stepping into the "trap" of DependencyProperty often.

At some point I realized that every single Change of any value is triggered somehow and somewhere, that can be an algorithm, a process, a user-input... and a lot of things, but NEVER it just changes by itself.

Get control about that triggers, hook directly at source and you never need DependencyProperty and even no INotifyPropertyChanged. I mean maybe I do something wrong or right, but all problems, and they are sometimes of serious difficulty, I solve with only RoutedEvents and Properties { get , set } -> And inside of get, set you can do SO much. Everthing that cannot be solved here, can be done with AddHandler and don't forget to RemoveHandler when not needed anymore. Also needed is a solid understanding of Threading and Dispatching in some cases. Also needed is a good knowledge how to work with Lambda expressions and Actions. (Probably not useable for windows phone etc. applications, guessing)

Respectively: A serious drawback is coding control and effort. For that approach I need to write more Code and have better documentation, the big advantage is better understanding what is actually happen within your application and what could happen, what are the extends. There is NO drawback in performance, it is even faster, because when you hook directly into your triggers, you are using the lightest and most appropriate form of an Approach - Executing Code ONLY when it is necessary and only that heavy that it is necessary.

Finally: DependencyProperties could make sense in very responsive applications where you actually DON't KNOW the possible relations and reactions. That could be over a million possible cases -> You don't want to have control over those, you would never finish your product. Caveats: Not everything that looks like it is producing a ton of unknown cases are unknown. You can work with RANGES (from x to y) and write algorithms to regain control over thousands of possible cases with just one method.

So that are my two cents: DependencyProperties and INotifyPropertyChanged is not needed in most of the cases and just a way of having an easier coding life at the cost of actually understanding your product and (sometimes) performance.

(Notification to myself: I write this because I just came into a situation where I was thinking I need DependencyProperty, this time for real.. but no.. one hour of thinking and the solution was easy, found the trigger.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜