Introduction
Any attempt at mastering a technology, any technology, requires a good understanding of its foundations. This understanding makes it possible to grasp the more complex aspects of that technology; Windows Presentation Foundation (WPF) is no different.
In this first chapter, we'll discuss recipes concerning the very foundations of WPF – what makes it tick—and also along the way, what makes it unique.
XAML
The first noticeable facet of WPF is XAML (eXtensible Markup Language). XAML is an XML based language used in WPF to declaratively create user interfaces. Actually, XAML has nothing to do with UI. It's merely a declarative way of constructing objects and setting their properties. In fact, it's leveraged in other technologies, such as the Windows Workflow Foundation (WF), where it's used as a way of constructing workflows. To create objects in XAML, they must be "XAML friendly" – meaning they must have the following:
A public default constructor
Settable public properties
The second item is not strictly a requirement, but the lack of settable properties would make the object a bit dull. Note that starting with .NET 4, XAML is in fact capable of handling parameterized constructors, but WPF's XAML parser currently does not leverage that capability.
XAML is not an absolute requirement. In fact, you can create an entire application using C# or VB (or whichever .NET language you fancy) without a single XAML tag. However, that would be much more difficult and error prone with high maintenance costs, not to mention the difficulty of integration with your fellow designers.
XAML is about the what, not the how. This declarative style makes things easier (granted, after some getting used to), and is a paradigm shift in software development in general (the classic example in .NET being the LINQ-based technologies). XAML is neutral—it's not C# or anything like that—so other, non-developer tools can create or manipulate it. Microsoft provides the Expression Blend tool, which at its core, is a glorified XAML producer/consumer.
XAML and compilation
What happens to a XAML file? How is it tied to the code behind file created by Visual Studio? A XAML file is compiled by a XAML compiler that produces a binary version of the XAML, known as BAML. This BAML is stored as a resource inside the assembly and is parsed at runtime in the InitializeComponent
call to create the actual objects. The result is bundled with the code behind file (the typical Window
class is declared as partial
, meaning there may be more source files describing the same class) to produce the final code for that class.
Browsing a typical WPF application, we won't find the canonical Main
method, because it's generated by WPF. It constructs the singleton Application object instance and creates the first window specified by the
Application.StartupUri
property (if not null). We can find that code in the file App.g.cs
(g
stands for generated) inside the Obj\x86\Debug
sub-folder.
Dependency properties
.NET properties are nothing more than syntactic sugar over set and get methods. What those methods do is up to the property's developer. More often than not, a property is a thin wrapper over a private field, perhaps adding some validation logic in its setter.
WPF requires more out of its properties. Specifically, WPF's dependency properties provide the following:
Change notifications when the property's value is changed.
Validation handler called as part of a set operation.
Coercion handler that is able to "coerce" the provided value to an acceptable value.
Various providers can attempt to set the property's value, but only one such provider wins at a time. Nevertheless, all values are retained. If the winning provider goes away, the property's value is set to the next winner in line.
Property value inheritance down the visual tree (if so desired).
No memory is allocated for a property's value if that value is never changed from its default.
These features provide the basis of some of WPF's strong features, such as data binding and animation.
On the surface, these properties look the same as any other property—a getter and a setter. But no private fields are involved, as we'll see in the following recipes.