Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the WPF dependency property design save memory consumption?

I read this in the following link:-

http://www.informit.com/articles/article.aspx?p=688529&seqNum=2

However, because GetValue and SetValue internally use an efficient sparse storage system and because IsDefaultProperty is a static field (rather than an instance field), the dependency property implementation saves per-instance memory compared to a typical .NET property. If all the properties on WPF controls were wrappers around instance fields (as most .NET properties are), they would consume a significant amount of memory because of all the local data attached to each instance.

But eventually they are getting stored somewhere, how does it saves memory consumption ?

like image 496
teenup Avatar asked Aug 21 '11 08:08

teenup


People also ask

What are the advantages of dependency properties in WPF?

Dependency properties are stored in a dictionary of key/value pairs which is provided by the DependencyObject class. It also saves a lot of memory because it stores the property when changed. It can be bound in XAML as well.

What is advantage of dependency property?

Advantages of a Dependency Property The Dependency Property stores the property only when it is altered or modified. Hence a huge amount of memory for fields are free. It means that if no value is set for the property then it will return to the inheritance tree up to where it gets the value.

How does dependency property work internally?

A DependencyProperty maintains a static reference of all the DependencyProperty you register in WPF object hierarchy. It maintains a HashTable named PropertyFromName which it uses internally to get the DependencyProperty object. So in other word, each dependencyProperty object is registered in a global HashTable.

What is dependency property in WPF interview?

Dispatcher Object – It is defining the base class for all WPF types. Dependency Property – The object presents a property that can be used to set through data binding, automation, Styles, Animation. This object inherits values from the parent class and gives notifications for change as well.


2 Answers

First, suppose you create a class with a dozen properties. Create 100,000 of them. How many object references do you now have? 1,200,000.

Now implement a class called DependencyObject:

public class DependencyObject
{
    public DependencyObject()
    {
       LocalValues = new Dictionary<string, object>();
    }

    protected Dictionary<string, object> LocalValues { get; set; }

    public DependencyObject Parent { get; set; }

    protected object GetValue(string propertyName)
    {
       if (LocalValues.ContainsKey(propertyName))
       {
          return LocalValues[propertyName];
       }
       return Parent.GetValue(propertyName);
    }

    protected void SetValue(string propertyName, object value)
    {
       LocalValues[propertyName] = value;
    }
}

Build a derived class like this:

public class MyDependencyObject : DependencyObject
{
    public SomeType Property1
    {
       get { return (SomeType)GetValue("Property1"); }
       set { SetValue("Property1", value]; }
    }

    // create 11 more properties like this
}

Now create 100,000 instances of MyDependencyObject and set their Parent. How many object references are used (not counting the parent)? 300,000.

That's how property value inheritance works in dependency objects.

like image 20
Robert Rossney Avatar answered Nov 17 '22 21:11

Robert Rossney


See the following link: Dependency Properties.

What is declared by an object as a dependency property is in fact nothing more than an identifier. This static "property" is really a key which associates an object with a specific storage identifier. For example graphical objects have a Background property that can be set explicitly or through the use of templates or styles..

As long as a Dependency Property uses its default state (which is very common), it won't take up any additional memory since the default value will be used. The default value isn't stored per instance, it is stored per Dependency Property and it's set by metadata.

Example, notice how Brushes.Black is set as the default value

public static readonly DependencyProperty ForegroundProperty =
    DependencyProperty.Register(
        "Foreground",
        typeof(Brush),
        typeof(TextElement),
        new FrameworkPropertyMetadata(Brushes.Black, ...));

Think of it this way: Say you have four TextBlocks in Xaml

<StackPanel>
    <TextBlock .../>
    <TextBlock .../>
    <TextBlock .../>
    <TextBlock Foreground="Green" .../>
</StackPanel>

The three TextBlocks at the top have Foreground set to Black although you have never explicitly set it to Black. They are using their default value. So for the Foreground property for the three TextBlocks above, you only need one field (since it is a static field).

For the forth TextBlock though, you have explicitly set Foreground to Green, so that value is inserted into a dictionary as the local value for Foreground on this instance and thus requires additional memory (also, it will end up at place number 3 in the list below, overriding Setters, Triggers etc).

Also, see the following post by Josh Smith, it's a good read: Demystifying dependency properties

There is a well-defined set of rules which is used internally by WPF to figure out what the real value of a DP is. Here is a brief summary of the rules of precedence used when resolving the value of a DP (read more about it here):

  1. Property system coercion
  2. Active animations, or animations with a Hold behavior
  3. Local value
  4. TemplatedParent template
  5. Style triggers
  6. Template triggers
  7. Style setters
  8. Theme style
  9. Inheritance
  10. Default value from dependency property metadata

Edit: To answer the comment from Duane

If you explicitly set the value to the same value as the default value, it will still get stored as the local value. This can easily be verified with the following Xaml.

Both TextBlocks will have Foreground set to Black, but the later has a local value set. The Style will only be able to set Foreground on the first TextBlock and not the later since Style setters has lower priority than local value.

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Green"/>
        </Style>
    </StackPanel.Resources>
    <TextBlock Text="Displays in Green"/>
    <TextBlock Foreground="Black" Text="Displays in Black"/>
</StackPanel>
like image 193
Fredrik Hedblad Avatar answered Nov 17 '22 21:11

Fredrik Hedblad