For my first blog entry, I'll be talking about dependency properties.
When I first started learning WPF, I stumbled across this new concept and I wondered „Another type of properties? But what's wrong with goo', ol' .NET properties?!“ And later, it turned out that nothing was wrong with .NET properties, and that dependency properties were not actual properties in .NET sense. After a couple of months of experience in WPF, I decided to help you to easier understand dependency properties.
Let's take a look at how to create a simple dependency property. Create a new „WPF Application“ project and create a new WPF user control. Replace its XAML with the following XAML (watch out for the correct namespace in x:Class) and add dependency property definition in the code-behind:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Rectangle Width="200" Height="200" Fill="Yellow" />
< /UserControl>
public static readonly DependencyProperty BrightnessProperty = DependencyProperty.Register(
"Brightness",
typeof(int),
typeof(UserControl1),
new PropertyMetadata(50)
);
public int Brightness
{
get { return (int)GetValue(UserControl1.BrightnessProperty); }
set { SetValue(UserControl1.BrightnessProperty, value); }
}
If you compile it, there should be no errors.
What we have there is a simple dependency property named „BrightnessProperty“ on a type named „UserControl1“, so when you want to use it in your WPF application, you'd access it like „UserControl1.BrightnessProperty“. Let's check out the code.
First we create BrightnessProperty, a public static readonly member of UserControl1, which is in .NET terms actually a field, not a property. And now comes the confusing part: we create a .NET property named Brightness, which is actually called a „wrapper property“ of dependency property BrightnessProperty. But this wrapper property is NOT dependency property and is totally unnecessary for the dependency properties subsystem to work. The only reason why we must create is because of the XAML. XAML requires wrapper property just for the compile-time, and avoids it completely in run-time. So, if you're not using your dependency property from the XAML, feel free to skip writing wrapper properties (although it is certainly a good habit to write them).
Also, since WPF runtime doesn't use wrapper properties, don't make the mistake (as I did) of putting anything in them besides simple get/set value.
I order to show you what I just said, let use our control from the previous listing. Go to Window1.xaml and change it with the following XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Grid>
<my:UserControl1 x:Name="p1" Brightness="30" />
< /Grid>
< /Window>
Pay special attention to namespaces (bolded in listing) in order to avoid errors.
Here we have put our control to work. Note that we are setting „Brightness“ to value 30. In this way XAML editor uses wrapper property to access dependency property in compile time. Without wrapper property, you couldn't assign values to custom dependency properties through XAML (but you can through code-behind, of course).
Now put the breakpoint in get and set accessors in our Brightness property and start debugging the project. You will see that the application will not hit the breakpoint, confirming that WPF runtime doesn't use wrapper properties.
So, to wrap up my first entry:
- Dependency properties are actually static fields of classes.
- XAML uses wrapper properties around dependency properties in order to compile correctly.
- In runtime, WPF skips wrapper properties and assigns and reads values of your dependency properties directly, so don't put any custom code in wrapper properties.
12. svibanj 2008.