Dependency Properties – Background for Custom Controls

In  a previous post I began talking about Custom Controls, and I will continue that discussion over the next few days and weeks even as I start producing videos on the topic.

It turns out that the more you look at Custom Controls, the deeper you get into the Silverlight UI architecture, and there is much to see.

As an example of this phenomenon, in writing about Custom Controls, you quickly realize that sooner or later you must describe and explain the Dependency Properties System in Silverlight. This brings great joy to my heart, because it is one of the more interesting and one of the less discussed aspects of Silverlight programming

So this evening I'm going to leap ahead (a bit out of order) and introduce this system, though by no means cover it in depth in one blog post. 

(Written late Tuesday, posted early Wednesday)

Understanding Our Roots

Traditional C# classes consist of

  • Methods
  • Events
  • Member Variables
  • Properties

You can easily view these in the Object Browser in Visual Studio (all but the member variables, which are almost always marked private and not shown).

ObjectBrowserUIButtonNoCircles

[Note, image cut down to save space]

C++  did not have properties (nor running water, nor electricity). Back in those dark days, if we wanted to provide access to the value of a member variable, we created methods to do so.

Thus, you ended up with funny looking code like this:

overallApproval = jesse.GetApprovalAverage() + tim.GetApprovalAverage();

Rather than the more natural,

overallApproval = jesse.Approval + tim.Approval;

Properties were brilliant. They looked to the class author just like methods, but they looked to the class consumer just like variables.

This was crucial. The class author was free to continue to obtain the actual value from backing variables or anywhere else:

   1: private double approval = .4;
   2: public double Approval
   3: {
   4:    get
   5:    {
   6:       if ( currentViewer.ID == "ScottGu" )
   7:          return .9;
   8:       else
   9:          return approval;
  10:    }
  11: }

In practical experience, most properties are backed by member variables, though that is by no means universal – some are backed by values in persistent storage, and some are computed dynamically. But some very large percentage are backed by member variables, which is why Auto-implemented properties were invented (and they are also brilliant). Prior to C# 3.0 my code was peppered with annoying properties that looked like this:

   1: private int myMember;
   2: public int MyProperty
   3: {
   4:    get { return myMember; }
   5:    set { myMember = value; }
   6: }
   7:  

Auto-implemented properties let me write

public int MyProperty { get; set; }

which C# 3.0 interpreted as an exact equivalent – the IL code produced is identical. 

Yes, there are a few restrictions, the only significant one is that I can't do anything in the getter or setter except get and set the value. If I need to do anything else, it's back to the full getter and setter – leaving me no worse off than before. 

So What's Wrong With Properties?

As terrific as properties are, they just don't cut it in a declarative, animated, data-bound world. Think about the property that describes the position of an object that is being animated; that value is changing very rapidly, in real time, possibly in response to conditions that cannot be anticipated at compile time. Properties just were not invented for that.

A Hidden World Underneath Your Feet

It turns out that WPF and Silverlight have extended properties in a way that you might never have suspected, and really never need be aware of until and unless you decide to create your own controls.

In fact, it is entirely possible to write completely robust Silverlight applications for quite a long while without knowing that underneath the surface lies an entirely new and very powerful system, humming gently and doing its work.

When you do learn of it, however, the revelation is not unlike the moment when you learned that beneath the streets of your city was a gargantuan system of pipes and wires that made up the city’s power and water grid. A bit unsettling at first, and then totally fascinating (at least it was to me, but I'm a nerd). 

In brief:  the Dependency Properties system allows Silverlight to determine the value of a property not from a value at compile time, but rather dynamically from a number of different inputs: specifically from

  • Resources

allowing you to write code that looks like this

   1: <UserControl.Resource>
   2:   <SoldColorBrush x:Key="ABrushFromAResource" Color=Red" />
   3: </UserControl.Resource>

and then later in your Xaml file use that code like this

   1: <Button "{StaticResource ABrushFromAResource theBrush}" width="100"
   2: height="100" />

  • DataBinding

By using Dependency Properties the value of the property can be set based on late binding to a data source.

  • Animation

Animation makes the highest demands on a property; requiring that its value change quickly over short periods of time. It is animation that makes crystal clear that the Dependency property system had  to be build, that the extant Reflection system could never be sufficiently performant

Dependency Property Precedence

One issue that quickly arises is this: if a property might be affected by multiple sources (the template says I should be red, but the data binding says I should be blue, but the animation just turned me to violet" – who wins?

To solve this problem, a non-negotiable (and quite logical) order of precedence was established. Like all such things, there is some complexity to handle border cases, but the essence of it is straight forward, and just what most of us would do given enough time (say 5 years) to think it through:

  • Animation always wins
  • IN the absence of animation, local values (values on the object itself) take precedence
  • If neither of the above apply, use the templated value
  • If none of the above apply use the style
  • Failing all of that, use the default value

But Wait, There's More…

There is always more to say, but this general overview of the Dependency Property system will serve as a solid foundation for our next exploration of custom controls. We'll return to the Dependency Properties system in more depth as we go.

 

Thanks!

 

-jesse

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in z Silverlight Archives. Bookmark the permalink.