User Controls and Dependency Properties - Page 6
       by kirupa  |  19 November 2007

In the previous page, while you may not realize it right now, you took a giant leap in making your user control more usable. In this page, you'll see the results of the changes you made as well as learn what exactly the changes you made are.

Using our UserControl...Finally!
At this point, you copied and pasted into your InfoRectangle.xaml.cs file some code and hit F6 to make sure everything was working properly. Go back into Blend and rebuild your solution by going to Project | Build or by pressing Ctrl + Shift + B.

In Window1.xaml, select or insert an instance of your InfoRectangle user control with your mouse, and take a look at the Miscellaneous panel in your Properties pane:

[ Do you see anything interesting in your Miscellaneous panel? ]

Notice that you now have a field called InfoText visible. Select that field and type  something such as Hello and press Enter:

[ enter the word Hello in your InfoText property ]

After you have pressed Enter, notice that the text inside your user control also changed to display what you entered in the InfoText field:

[ your InfoText user control's text has now changed ]

You can repeat that for every other InfoRectangle user control you have displayed in your Artboard. If you look at the XAML for your user control, you will see that the InfoText property was set directly:

<UserControlSample:InfoRectangle .... InfoText="New Text!"/>

If it wasn't for what you did earlier, you could not have set the value for your text via XAML. You would have had to write C# code instead to directly add your text to the appropriate InfoRectangle instance.

Deconstructing the Code  for the Dependency Property
The code you copied and pasted helped define a dependency property. A dependency property is just like a regular property, except this property is tied deeply into the WPF property system. I will explain more along the way, but let's first explore the mechanics of the three parts that are needed to create a dependency property.

Part 1: The CLR Wrapper
The first part is the CLR wrapper that allows your dependency property to be accessed via code:

public string InfoText
{
get
{
return (string)GetValue(InfoTextProperty);
}
set
{
SetValue(InfoTextProperty, value);
}
}

In .NET, Properties allow you to easily assign and retrieve a value using either the get or set keyword. In most general cases, the property itself is responsible for storing the data, but in the case with dependency properties, the data is stored deep inside the property system.

The only way to gain access to that data is by either using GetValue or SetValue on the dependency property itself, and that is what we are doing.

Now, you may be wondering why this is known as a CRL wrapper. The main reason is that this runs only when InfoText is called in code. When you used Blend to set the value of the InfoText property from the Miscellaneous panel, you didn't access this section of code at all. It was all done via XAML as shown as shown earlier!

That isn't to say that you can avoid this section of code if you never plan on using C# code to set your properties. When compiling your application, this section of code is needed. When you actually run your application, though, this code is bypassed when you use XAML to set the property.

Because our InfoText property is only called from code, you should be careful to not add any extra code to either your get or set sections unless you want that code to only run when this property is accessed via code. After all, any changes to our InfoText dependency property made directly via XAML (such as what you did in Blend) will not cause your get/set statements to execute at all.


Part 2: The Static Field Declaration
In this really long line (broken into several lines for space reasons), you actually declare and register your dependency property:

public static readonly DependencyProperty InfoTextProperty =
   DependencyProperty.Register(
      "InfoText",
      typeof(string),
      typeof(InfoRectangle),
      new FrameworkPropertyMetadata(
         new
PropertyChangedCallback(ChangeText)));

The first thing to note is that there is a naming convention that you must follow. Your static field must be your dependency property's name appended by the word Property. That is why, in the above code, our static field declaration is called InfoTextProperty.

The next thing to do is register this property:

public static readonly DependencyProperty InfoTextProperty =
   DependencyProperty.Register(
      "InfoText",
      typeof(string),
      typeof(InfoRectangle),
      new FrameworkPropertyMetadata(
         new PropertyChangedCallback(ChangeText)));

 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, WPF has an advanced property system that keeps track of the various dependency properties used in an application. There are various handshakes that you need to know in order to access the property system, and depending on how you shake its hand, different results are possible.

Let's look at our DependencyProperty's Register method in greater detail:

public static readonly DependencyProperty InfoTextProperty =
   DependencyProperty.Register(
      "InfoText",
      typeof(string),
      typeof(InfoRectangle),
      new FrameworkPropertyMetadata(
         new PropertyChangedCallback(ChangeText)));

The first argument you pass in refers to the name of the DependencyProperty you wish to register. Since our DependencyProperty is called InfoText, that is the value you enter here. If you were to change your value to something else besides what you named your DependencyProperty, you will find that, while your code wont produce an error, assigning values to your InfoText property via XAML is routed through your CLR wrapper. There are some other (more unwanted) side effects such as issues with applying styles, data binding, and so on, so be sure to specify your dependency property's name.


We covered quite a bit of ground in this page, but there is more code explanation to do. Let's continue digging through our code on the next page.

Onwards to the next page!

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.