Properties, Dependency Properties, and WPF 
by Charles Petzold

Listing One

<!-- PropertySettingsDemo.xaml by Charles Petzold -->

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      WindowTitle="Property Settings Demo"
      Title="Property Settings Demo"
      FontSize="36pt">
    <!-- Resources -->
    <Page.Resources>
        <Style x:Key="styleTextBlock" TargetType="TextBlock">
            <Setter Property="FontSize" Value="24" />
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="HorizontalAlignment" Value="Center" />
        </Style>
    </Page.Resources>

    <DockPanel>
        <ScrollBar Name="scroll"
                   DockPanel.Dock="Left"
                   Orientation="Vertical"
                   Minimum="10" Maximum="100" Value="20" />

        <!-- StackPanel with six TextBlock elements -->
        <StackPanel>
            <TextBlock Text="Hello XAML #1" FontSize="16" 
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #2" FontSize="12"
                       Name="txtblk2" HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #3"
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #4" Name="txtblk4">
                <TextBlock.LayoutTransform>
                    <RotateTransform />
                </TextBlock.LayoutTransform>
            </TextBlock>
            <TextBlock Text="Hello XAML #5"
                   FontSize="{Binding ElementName=scroll, Path=Value}"
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #6" 
                       Style="{StaticResource styleTextBlock}" />
        </StackPanel>
    </DockPanel>

    <!-- Animations -->
    <Page.Triggers>
        <EventTrigger RoutedEvent="Page.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="txtblk2"
                                Storyboard.TargetProperty="FontSize"
                                To="48" Duration="0:0:2"
                                AutoReverse="True" 
                                RepeatBehavior="Forever" />
                    <DoubleAnimation Storyboard.TargetName="txtblk4"
                                 Storyboard.TargetProperty=
                                     "LayoutTransform.Angle"
                                     To="360" Duration="0:0:10"
                                     RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Page.Triggers>
</Page>
=================DR. DOBB'S JOURNAL===============
ARTICLE:       Properties
ISSUE:         VISTA SUPPLEMENT
SECTION:       Feature
AUTHOR:        Charles Petzold
               cp@charlespetzold.com
FILENAME:      PETZOLD.DOC
LENGTH:        2500 words
HED:           Properties, Dependency Properties, and WPF 
DEK:           Putting XAML to work
BYLINE:        Charles Petzold
BIO:           Charles has been writing about Windows application programming for over 20 years. His most recent book is Applications = Code + Markup: A Guide to the Microsoft Windows Presentation Foundation and he is currently working on a book about 3D graphics under the WPF. He can be contacted at www.charlespetzold.com. 

PULLQUOTES:    1) Dependency properties are so important that data binding and animation don't work with anything that's not a dependency property
 
FIGURE(S):     1) Figure 1: Animations generated by PropertySettingsDemo.xaml. 

LISTINGS:   Listing One -- 60 lines
 
TEXT:

Throughout the 20-odd years of its existence, Microsoft Windows has always exhibited a fairly high degree of backward compatibility. With relatively few examples, programs written for one version of Windows continue to run on the next. 
     Windows Vista continues this trend: It runs programs written for the Win32 API, for the Microsoft Foundation Classes (MFC), for Visual Basic, and for the Windows Forms library of .NET 1.0 and 2.0. 
     Vista also implements a new application programming interface called the Windows Presentation Foundation (WPF), previously known under the codename "Avalon." The WPF is also available under Windows XP with the .NET Framework 3.0 installed. (Alternatively, you can think of WPF as part of .NET 3.0, which can be installed under XP but which is built into Vista.)
     Compared with the previous mainstream APIs for Windows, the WPF breaks new ground by implementing two complementary programming interfaces. You can write entire WPF applications in your favorite .NET-compliant programming language such as C# or Visual Basic .NET, but you can also write at least parts of the application using the XML-based Extensible Application Markup Language (XAML, pronounced "zammel"). 
     Although XAML has been classified as a declarative programming language, it is mostly restricted to instantiation and initialization of visual objects. In simple scenarios, you use XAML to define the layout of controls on your windows, and you use code to define event handlers for these controls. You compile the XAML and code together into an executable. 
     However, several features of the WPF--such as data-binding and animation--let your write interesting XAML files that stand by themselves. These standalone XAML files can be launched under Vista or .NET 3.0 just like other executables, and they run in the Web browser.

Instantiation and Initialization
Let's look at some C# code first. Here is some code to create and initialize a ScrollBar control, perhaps in the constructor of a Window class where the ScrollBar appears:

ScrollBar scr = new ScrollBar();
scr.Orientation = Orientation.Vertical;
scr.Minimum = 10;
scr.Maximum = 100;
scr.Value = 20;

     Orientation, Minimum, and Maximum look like fields of the ScrollBar class, but they are actually properties. The Orientation property is set to a member of the Orientation enumeration; the other properties are of type double. Properties were introduced in .NET 1.0 as a nice clean syntax to replace pairs of Get and Set methods, for example, GetMinimum and SetMinimum. 
     Very often, a .NET property provides a public interface to a private field. Traditionally, a property such as Minimum would be associated with a private field initialized to a default value:
     
private double min = 0;

     The definition of the Minimum property starts out looking like a method, but without any parentheses or argument list. Within the property definition are two accessors, labeled get and set with code that might otherwise be found in the corresponding GetMinimum and SetMinimum methods:

public double Minimum
{
    get
    {
        return min; 
    }
    set
    {
        min = value;
        ...
    }
}

     The get accessor must terminate with a return instruction with a value of the proper type. Within the set accessor, the word value indicates the value the property is being set to. Notice that ominous ellipsis. Traditionally, what happens next depends on how the ScrollBar class is structured. The object might need to redraw itself based on the new value of Minimum. Perhaps the Value property of ScrollBar is no longer within the range between Minimum and Maximum. Value might then need to be reset, which might trigger an event.
     Properties are sometimes called "smart fields" because code is evoked when a property is set or retrieved. The object has the opportunity to react in some way, and that's just not the case with fields. An object doesn't know a field has been set until it checks the value. 
     My illustration of the Minimum property is actually not how properties like these are defined in the Windows Presentation Foundation. Some properties are, but many are not. Many WPF properties are actually a somewhat different kind of animal called "dependency properties", and the reasons for the extra overhead in the WPF is one of the themes of this article.
     Originally .NET properties seemed to do little more than provide an elegant syntax to replace Set and Get methods. A bonus was revealed when it was time to represent classes in XML-based files, including XAML. The property names simply became XML attributes. Here's the equivalent XAML of the ScrollBar creation and initialization logic:
     
<ScrollBar Orientation="Horizontal" Minimum="0" Maximum="150" />

     The problem with this particular ScrollBar is that it doesn't have any effect on anything else in the program. In the general case, you'll want an event handler that's triggered whenever the Value property of the ScrollBar changes. You indicate the method you want to use as the handler for the ValueChanged event in C# code like this:

scr.ValueChanged += ScrollBarValueChanged;

     In XAML, you can indicate the event handler like so:

<ScrollBar Orientation="Horizontal" Minimum="0" Maximum="150"
     ValueChanged="ScrollBarValueChanged" />

     However, the handler itself needs to be written in code.
     There's another way the ScrollBar could be used, and this alternative approach doesn't require an event handler. It's a data binding. Basically, you establish a link between the Value property of the ScrollBar and a property of some other object. You can establish this binding in code, but it's actually easier to do it in XAML.

A Stack of Text
In a WPF program, properties can be set in a variety of ways. They can be set explicitly through code or markup, they can be set through data bindings, they can be set through animations or styles, and they can be set in other ways beyond the scope of this article. Listing One is an XAML file named PropertySettingsDemo.xaml that provides a glimpse into this flexibility. If you're running Windows Vista or the .NET Framework 3.0 under Windows XP, you can simply launch this file as if it were a program, and it runs in your Web browser. It contains two animations, so what you'll see might look something like Figure 1.
     In the center of the PropertySettingsDemo.xaml file are six TextBlock elements, five of which have their FontSize properties set in five different ways. (The rotating TextBlock is just a gratuitous bonus, but I use it to make a point.) TextBlock is a relatively simple element used to display chunks of text. The six TextBlock elements are grouped as children in a StackPanel element, which stacks its children vertically. The StackPanel is itself a child (along with a ScrollBar) of a DockPanel, which is a child of the top-level element, a Page.
     Notice first that the whole program contains no explicit coordinate positions or sizes except for the FontSize property itself. Each TextBlock is entirely capable of determining what size it needs to be, and the StackPanel can arrange these six elements based on those sizes. Also notice that StackPanel's arrangement of the elements dynamically accommodates the animations.

* The first TextBlock element is assigned an explicit FontSize value of 16. In the WPF, values such as this are in units of 1/96 inch, which isn't exactly an industry standard of some sort except that video displays under Windows commonly use a resolution of 96 DPI. The value of 16 translates to 1/6 inch or 12 points.
* The second TextBlock element is assigned a FontSize of 12, but it's used only as a base value for the first of the two animations. The animation takes the FontSize up to a value of 48 over two seconds, then back down over the next two seconds, and repeats the process forever.
* The third TextBlock doesn't have a FontSize property set, which would normally cause the value to be set to its default, which might be 11 (under Windows XP) or 12 (under Vista). But notice that the top-level Page element has its own FontSize property set to 36 points. That value is inherited by any descendent TextBlock that doesn't have its local FontSize property set.
     You might imagine property inheritance happening in one of two ways. Perhaps the parent element pushes property values on the child. Whenever the parent detects that it's getting another child assigned to it, it sets the FontSize property of the child to its own FontSize property. Or maybe it's a pull mechanism, where the child detects when it's being assigned a parent, and then queries the parent's FontSize property.
     The problem with these two theories, however, is that neither DockPanel nor StackPanel implement the FontSize property, and they know nothing about the FontSize property. The inheritance of the FontSize property is effectively skipping two generations, so the mechanism is obviously more complex than simple push or pull logic might suggest.
* For the fourth TextBlock, I considered having the animation change a ScaleTransform so the TextBlock would grow and shrink in size like the second one, but I decided to add a little variety and apply the animation to a RotateTransform. 
* The fifth TextBlock binds its FontSize property to the Value  property of the ScrollBar docked at the left of the page. You can use the ScrollBar to change the FontSize to values between 10 and 100 units.
* The sixth TextBlock sets its Style property of a Style object defined as a resource towards the top of the file. The style sets the FontSize property, as well as the horizontal alignment of the element and its color.

Measure and Arrange
The WPF was conceived early on as supporting automatic sizing and dynamic layout, so it's not surprising to see this mechanism implemented as a fundamental part of WPF architecture. 
     Layout occurs in two passes, and begins with the highest level element, in this example, the Page. Every element can have zero or more children. Elements that have multiple children go by the generic name of "panel" and are the primary layout mechanisms. The Panel class has several descendents, including DockPanel, StackPanel, WrapPanel, Grid, UniformGrid, and Canvas, which is the panel that lets you position controls and elements with explicit two-dimensional coordinates. 
     Layout begins with a call to the virtual MeasureOverride method in the top-level element. (This method is defined in FrameworkElement and it has a rather odd name because it essentially replaces a similar method in the UIElement class named MeasureCore.) The parameter to this method is an available size. The MeasureOverride method is responsible for calling the Measure method on all its children (if any), which in turn causes a call to the child's own MeasureOverride method. This is how measuring proceeds from the top of the element tree to the bottom. 
     The Measure method is responsible for determining what size the element should be. When Measure returns, the parent examines the DesiredSize properties of its children and derives a composite size. For example, a StackPanel with a vertical orientation sums the desired heights of all its children.
     The second layout pass begins with a call to virtual ArrangeOverride to the top-level element. The parameter indicates a final size for the element. The parent's job is to arrange all its children within that space with a call to each child's Arrange method, which then calls the child's ArrangeOverride method to ripple through the rest of the layout.
     Although panels are commonly used to lay out controls and elements within a page or window, they can also be used inside buttons and other controls. For example, a Button might contain a StackPanel, which then contains text and bitmaps.
     As the animations are going on inside PropertySettingsDemo.xaml, the StackPanel is continuously rearranging its children based on their changing sizes.

Retained Graphics
What's not going on in PropertySettingsDemo.xaml is a lot of redrawing--at least by most of the TextBlock elements. In earlier Windows programming environments, when a control is moved from one part of a window to another, it needs to be redrawn. The surface of the window is invalidated, which generates repainting calls.
     In contrast, the WPF has a retained graphics system. Once an element draws itself--a process that happens in the virtual OnRender method--it doesn't need to draw itself again unless something happens to cause it to require a new appearance. This is the case with the TextBlock whose FontSize is animated, and the one whose FontSize is bound to the ScrollBar. A new FontSize requires redrawing. But the others are drawn only once, including the one being rotated.
     To make this program more efficient, it would be better to change the size of TextBlock elements with a ScaleTransform rather than altering the FontSize. The transform is performed on the retained graphic object rather than requiring the element to redraw itself.

Properties and Dependency Properties
The developers of the WPF realized they were designing a system where properties could be set in a variety of ways, some of them possibly interacting with each other. It was important to construct a system where these interactions would have strict levels of precedence and predictability. Their solution was to build a layer on top of the existing property mechanism called "dependency properties." 
     If you were privy to source code for TextBlock, you would probably find it has something this code:

public static DependencyProperty FontSizeProperty =
  DependencyProperty.Register("FontSize", typeof(double), 
     typeof(TextBlock), new FrameworkPropertyMetadata(default, 
       flags, FontSizeChanged), ValidateFontSize);

     This is definition of a static field named FontSizeProperty--that is, the FontSize property name followed by the word Property--of type DependencyProperty. The initialization code that follows could alternatively be in the class's static constructor. This code defines the name of the property, its type (double), its owner, and a default value, indicated by default. Let me come back to the flags parameter.
     The code also references two static methods. One provides a systematic approach to validation. The ValidateFontSize method returns True if the FontSize property is being set to a value at least 1/300 inch.

static bool ValidateFontSize(object obj)
{
  double fntsize = (double) obj;
  return fntsize > 1.0 / 300;
}

     I don't have access to WPF source code, so I can't tell you precisely what happens in the method I've called FontSizeChanged. The method is called whenever the FontSize value changes, but it might not exist at all, and if it does, it probably only performs some preparation work, such as creating an object of type FormattedText. Anything more is unnecessary, as you'll see soon.
     The TextBlock class also includes a regular FontSize property, but it only refers to the FontSizeProperty dependency property:

public double FontSize
{
  get { return (double) GetValue (FontSizeProperty); }
  set { SetValue(FontSizeProperty, value); }
}

     The GetValue and SetValue methods are defined by the DependencyObject class. Any class that implements dependency properties must derive from DependencyObject.
     I haven't yet discussed the flags parameter in the dependency property initialization code, and for the FontSize property, these flags are crucial. The flags parameter consists of zero or more members of the FrameworkPropertyMetadataOptions enumeration, combined with the bitwise OR operator. For FontSize, there are three flags set:

* The AffectsMeasure flag indicates that whenever the FontSize property changes, the current measure information for the element should be invalidated. This causes a call to the MeasureOverride method, which then triggers a call to ArrangeOverride so the element can be repositioned based on its new size. 
* The AffectsRender flag indicates that whenever the FontSize property changes, the current visual appearance of the element is invalidated, generating a call to OnRender. Notice that the AffectsMeasure and AffectsRender flags are independent. For example, the Foreground property, which indicates the color of the text displayed by the TextBlock, has its AffectsRender flag set but not AffectMeasure because the color doesn't affect the size of the element.
* Finally, the Inherits flag is set, indicating that the FontSize property can be set from the element's closest ancestor. 

     Yes, the TextBlock element is still responsible for determining how large it needs to be and what it should look like, but all the notification mechanisms for property changes have been encapsulated in the DependencyProperty object. TextBlock doesn't have to invalidate its measure or rendering information. Nor does TextBlock have to worry about how property inheritance works. The retained graphics system provides that any change to these properties won't cause any flickering on the screen.
     Dependency properties are so important that data binding and animation don't work with anything that's not a dependency property. The data-binding and animation markup in PropertySettingsDemo.xaml seems to refer to the FontSize property, but binding and animation classes actually access the FontSizeProperty field directly. 
     That means that if you're writing a WPF class in which you want properties to be bindable or animatable, you'll want to make them dependency properties, and in the process save yourself from implementing a lot of custom notification logic.




Listing One

<!-- PropertySettingsDemo.xaml by Charles Petzold -->

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      WindowTitle="Property Settings Demo"
      Title="Property Settings Demo"
      FontSize="36pt">
    <!-- Resources -->
    <Page.Resources>
        <Style x:Key="styleTextBlock" TargetType="TextBlock">
            <Setter Property="FontSize" Value="24" />
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="HorizontalAlignment" Value="Center" />
        </Style>
    </Page.Resources>

    <DockPanel>
        <ScrollBar Name="scroll"
                   DockPanel.Dock="Left"
                   Orientation="Vertical"
                   Minimum="10" Maximum="100" Value="20" />

        <!-- StackPanel with six TextBlock elements -->
        <StackPanel>
            <TextBlock Text="Hello XAML #1" FontSize="16" 
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #2" FontSize="12"
                       Name="txtblk2" HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #3"
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #4" Name="txtblk4">
                <TextBlock.LayoutTransform>
                    <RotateTransform />
                </TextBlock.LayoutTransform>
            </TextBlock>
            <TextBlock Text="Hello XAML #5"
                   FontSize="{Binding ElementName=scroll, Path=Value}"
                       HorizontalAlignment="Center" />
            <TextBlock Text="Hello XAML #6" 
                       Style="{StaticResource styleTextBlock}" />
        </StackPanel>
    </DockPanel>

    <!-- Animations -->
    <Page.Triggers>
        <EventTrigger RoutedEvent="Page.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="txtblk2"
                                Storyboard.TargetProperty="FontSize"
                                To="48" Duration="0:0:2"
                                AutoReverse="True" 
                                RepeatBehavior="Forever" />
                    <DoubleAnimation Storyboard.TargetName="txtblk4"
                                 Storyboard.TargetProperty=
                                     "LayoutTransform.Angle"
                                     To="360" Duration="0:0:10"
                                     RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Page.Triggers>
</Page>




9


