This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.
In C#, creating properties in code is very easy. A property called AuthorName would look like the following:
public string AuthorName
{
get;
set;
}
The above code, known as a CLR property, is good enough for you to use in most cases that involve setting and accessing a value. A slight wrinkle in this perfect fabric occurs when you are using Silverlight and want to do more.
While you can still use properties such as what I've shown above, Silverlight introduces more ways to set and access a value - ways that a CLR property simply cannot handle. Some of these ways involve animations, data binding, styling/templating, and more. They go beyond simple setting and getting via code.
To deal with this, you have a new type of a property known as a dependency property. In this article, I will show you how to create a dependency property in Silverlight.
The best way to get introduced to dependency properties is to look in detail at what one looks like. The above AuthorName property defined as a dependency property will look as follows:
public string AuthorName
{
get { return (string)GetValue(AuthorNameProperty); }
set { SetValue(AuthorNameProperty, value); }
}
public static readonly DependencyProperty AuthorNameProperty = DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
Whoa! What was a few lines earlier now has turned into more than a few lines of mostly incomprehensible code. Let's try to make sense of all this.
The basic structure of a dependency property is made up of two things. First, you have your CLR wrapper:
public string AuthorName
{
get { return (string)GetValue(AuthorNameProperty); }
set { SetValue(AuthorNameProperty, value); }
}
This wrapper provides you with easy access to the AuthorName property just like you would expect with any old CLR property that you can declare. Internally, it is a bit different in that the get and set methods call GetValue and SetValue respectively on a property called AuthorNameProperty.
The CLR wrapper is the first item that makes up your dependency property. The second item is what is known as a dependency property identifier, and in our code, that is represented by AuthorNameProperty:
public static readonly DependencyProperty AuthorNameProperty = DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
This line is what reconciles your above CLR wrapper with the property system that lives beneath Silverlight. This line can be divided into two parts as well. The first part is where you simply declare the identifier:
public static readonly DependencyProperty AuthorNameProperty = DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
Almost always, your type will be DependencyProperty, and its modifiers will be public, static, and readonly. The second part is where you initialize your dependency property identifier by registering it:
public static readonly DependencyProperty AuthorNameProperty = DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
Registering your property is interesting because it really doesn't make a lot of sense because the behind the scenes details are hidden from view. The main thing to remember is that, deep under the hoods, Silverlight has an advanced property system that keeps track of the various dependency properties used in an application.
Registering is where the various pieces of data that make up your dependency property get stored in that behind-the-alley warehouse that only Silverlight can access. In the next section, let's look at this registration process in greater detail.
In the previous section, you received a brief introduction to dependency properties. We ended by starting our deconstruction of the various things that make up a dependency property, more specifically, the register portion of your dependency property identifier. Let's continue from there.
Registering your dependency property is handled by DependencyProperty.Register. The Register method takes several arguments to help you customize some of the your dependency property's behavior, so let's look at those arguments now.
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
The first argument you pass in refers to the name of the DependencyProperty you wish to register. In general, try to keep the name the same as that of your dependency property such as what I've done.
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
The second argument defines the type of your dependency property. In our case, AuthorName is of type string, so that is the value I pass in to the Register method.
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
The third argument looks similar to what we wrote earlier. What you are specifying is the type of the class that owns this dependency property. This will vary depending on your scenario, but I have this dependency property declared inside a user control called AuthorTextField. Therefore, AuthorTextField is what I specify here.
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(""));
The last argument determines the metadata that will be carried along with this dependency property, and that is handled via the PropertyMetadata class. The term metadata often indicates something that isn't always useful, but that may be the wrong impression to get at this point. As you will see very shortly, the arguments you pass in here greatly affect how you may end up using the dependency properties in your application.
Into your PropertyMetadata constructor, you can specify the default value for your dependency property, a method to call when this property's value has changed, or both. In the next section, let's look at that in greater detail.
Like I briefly hinted at in the previous section, you can specify some additional information about your dependency property via the PropertyMetadata object.
The first variation you can do is change the default value your dependency property has. In my original code, I don't have a default value specified. If you were to examine this dependency property in Expression Blend, this is what you would see...a blank field:

[ no default value results in nothing being displayed ]
Let me specify a default value instead. My new Register code looks as follows with a default value specified:
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata("Sir Arthur Conan Doyle"));
When I rebuild my project and examine this property inside Blend again, notice what I see this time around:

[ your dependency property's default value is displayed ]
Instead of being greeted by a blank value, the default value I specified is what gets displayed instead. In my case, the default value is of type string because that is the type of my dependency property. In whatever you are doing, make sure that your dependency property's default value is the same type as your dependency property. In other words, don't put your value inside quotation marks to signify a string just because I have done so!
Another argument you can specify into your PropertyMetadata object is a callback method. This is a method that gets called each time your dependency property's value changes, and the call to this callback method will look as follows:
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata(new PropertyChangedCallback(AuthorNameChanged)));
In the above code, the name of my callback method is called AuthorNameChanged. What I haven't done yet is actually create my AuthorNameChanged method, but that is actually pretty straightforward:
private static void AuthorNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Code for dealing with author name changes
}
There are a few things that you should note. Because your dependency property identifier (and by extension your Register code) is a static variable, an event handler assigned to it such as AuthorNameChanged must be static as well.
The second thing to note are the two arguments passed into your callback method. The first argument is a reference to your DependencyObject object, and the second argument is a reference to your DependencyPropertyChangedEventArgs.
As long as your callback method has a static modifier and contains two arguments of type DependencyObject and DependencyPropertyChangedEventArgs, you are set! Each time your dependency property's value is changed, your callback method will get called and any code contained in it executed.
The final combination of arguments you can specify for your PropertyMetadata is one where you have both a default value as well as a callback method! This would look as follows:
DependencyProperty.Register("AuthorName", typeof(string), typeof(AuthorTextField), new PropertyMetadata("Sir Arthur Conan Doyle", new PropertyChangedCallback(AuthorNameChanged)));
I specify both my default value as well as create the new PropertyChangedCallback object with my callback method name provided as an argument.
Hopefully this article provided you with a good dose of information on how to use dependency properties in Silverlight 2. While articles like this treat dependency properties as being special, they are actually very common. For further reading on a practical use of dependency properties, I strongly recommend you read my 10 page article on dependency properties and user controls. While that article is WPF based, much of concepts will be similar in Silverlight.
Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence slop, ads, and algorithm-driven doodads. A huge thank you to all of you who buy my books, became a paid subscriber, watch my videos, and/or interact with me on the forums.
Your support keeps this site going! 😇

:: Copyright KIRUPA 2026 //--