When looking for a book on WPF, one title kept coming up over and over again. Windows Presentation Foundation Unleashed by Adam Nathan has been leading the Amazon charts in positive reviews, so we thought we would take it for a spin. Turns out, the book lives up to the hype.
In addition to our review, InfoQ was able to obtain not only a sample chapter, but also probably the most important chapter of the book. Chapter 3 includes coverage of WPF's property and event system, a system that is unlike anything else on the Windows platform.
WPF Unleashed opens with an in-depth look at XAML. While some other books leave this for later chapters, Nathan treats it as a core on which everything else is based. The author leaves little unsaid, ensuring even minor details like how the XAML namespaces map to traditional .NET namespaces are covered.
XAML
Chapter 2 starts with property elements and type converters. Type converters turn plain text like the word "White" into objects like "Windows.Media.Brushes.White". These are followed by C# examples which really show how much typing XAML saves.
Next up is markup extensions. This is a very non-XML like notation that is used for more advanced control over an element. One example from the text is:
Content='{Binding Path=Height, RelativeSource={RelativeSource Self}}'
Instead of nesting parameters and values inside an XML attribute, developers can write them out in long form as elements.
<Button.Content>
<Binding Path=Height>
<Binding.RelativeSource >
< RelativeSource Mode=Self/>
</Binding/>
</Button.Content>
After a brief section on the differences between lists and dictionaries in XAML elements, Nathan talks more about XAML extensibility. It turns out that XAML can be used to create any 'declarative-friendly' object. The rules are fairly simple; the .NET class just needs a default constructor and a way to set it up using properties. Since COM objects only have default constructors, most of them can also be used from XAML.
BAML
It is not talked about much, but XAML has a twin language called Binary Application Markup Language or BAML. As the name suggests, BAML is a binary representation of XAML that has been parsed and tokenized. It is not compiled into procedural code however, and can be easily converted back into XAML form. Both XAML and BAML can be loaded with only a line or two of code. According to the author, BAML versions of the UI are created stored as resource files when an application is compiled.
New Concepts
In chapter 3, Nathan introduces some new concepts that contribute to WPF's steep learning curve. A firm grasp of these concepts is essential when working with complex WPF designs.
First up is the difference between logical and visual trees. The logical view is basically composed of the controls, contents, and layout elements that for the UI. The visual tree breaks each control up into its constituent parts. For example, even a simple label might be made up of a Border, ContentPresenter, and TextBlock. This is not guaranteed however, as simply changing to a different Windows Theme may alter the visual tree. Nathan includes code for printing out the logical and current visual tree at runtime.
The next core concept is that of dependency properties. Unlike WinForms, where each control's properties are independent or minimally inherited, WPF allows for a rich set of declarative interaction between controls and their properties.
Dependency properties are an XAML-only concept. No other .NET language has any intrinsic understanding of them. Basically they are normal properties hooked into the WPF infrastructure. The author includes a sample code for creating your own dependency property.
The first use of dependency properties Nathan illustrates is change notification. One can set triggers such as when IsMouseOver is True, the Foreground becomes Blue. These are not like events in JavaScript or WinForms. When the trigger is no longer true, the properties it changed are reverted back to their original values automatically. The means the developer does not have to worry about caching or recalculating the original values, greatly reducing the amount of logic needed.
Properties in XAML are inherited from a number of sources. Just determining where the base value comes from can require checking the documentation. For example, if your Theme Style Trigger is not changing the value as you expected, it may be due to a Template Trigger or Style Setter overriding it. Despite giving the basic flow chart, Nathan points out that the DependencyPropertyHelper.GetValueSource function can be helpful when trying to figure these things out.
Attached properties are another new concept for WPF. Attached properties don't affect the control they are attached to. Rather, they affect all of the child controls. This allows you to do things like change the font for all text blocks in a given panel. Unlike WinForms, which would require tedious looping through the control collections, attached properties are a single line of declarative code.
Routed Events
Next up in Chapter 3 are routed events. Like dependency properties, these are an XAML concept not directly exposed to other .NET languages. Routed events can be tunneling, bubbling, or direct. Direct events are only raised in a specific control, much like WinForms events. Tunneling events work their way down the logical tree and are often prefixed with the word Preview. This gives developers the opportunity to cancel an event before it hits the control. If it is not canceled, then the 'real' event bubbles up from the control to the root element. At any point along either route, controls can respond to the event.
Commands
The final section in chapter 3 covers commands. Commands are a concept borrowed from MFC programming. They are in a way like events, but are not necessarily tied to a specific user action. Built-in commands are grouped into several broad categories. For applications, there are Cut, Copy, Paste, Save, Help, Print, etc. Media commands include functionality like Pause, Play, and NextTrack. There are other commands for editing, navigation, and components.
Like events, commands can be routed. This is helpful for more global commands like ApplicationCommands.Help. Some commands are automatically bound to keystrokes for a given control. For example, Cut, Copy, and Paste for text boxes. In addition, it is easy to declaratively setup controls that trigger commands in other controls.
Controls and Layout
With the basics covered, part II of Nathan's book goes into more practical aspects of programming with WPF. Chapter 4 introduces the controls and explains how they differ from their WinForms equivalents. It should be noted that while the controls significantly more powerful and flexible than those of WinForms, there are a lot fewer of them. Common ones like data-bound grids are completely missing and have to be recreated manually or with third-party libraries.
Nathan makes sure not to leave Tablet PC developers hanging. Sections in this chapter as well as the previous one specifically touch on stylus events and specialized controls like InkCanvas.
The next two chapters, as well as chapter 17, cover layouts. There is too much to summarize here, but rest assured it is all high-quality stuff your designers need to know.
Applications
Next up is a chapter on application structure and deployment. It starts with typical main form + dialogs styles applications and a brief discussion about ClickOnce vs Windows Installer. Then it moves into Navigation-based applications.
Navigation-based applications are actually very well supported by WPF. Designed similar to a browser, it has built-in "journal". This journal keeps a record of "pages" visited, giving the user access to back and forward buttons. Pages are simply XAML-based forms or files that are loaded into the navigation frame. Pages are held by the journal in a stack-based fashion, which often eliminates the need to recreate and reload a page.
Rather than dialogs, navigation-based applications use page functions. Page functions are loaded like normal pages. When "closed", the user is sent back to the previous page where an event handler receives any data the dialog contained. Making applications compatible with Windows Vista is covered next. This involves replacing dialog windows with Task Dialogs and using Aero Glass effects. Currently WPF doesn't support this directly, so both of these require using P/Invoke to call the underlying Win32 API. The fact that Nathan is willing to go beyond WPF when needed is one of the things that make this book stand out.
Vista Gadgets are covered next, but unfortunately not to any great depth. Just a short list of suggestions and a small code example is all the reader gets. XAML Browser Applications are next up, but that has been largely superseded by the release of SilverLight.
Professional Features
At this point, most casual developers will have enough information to start cranking out applications. But for the more advanced developer, this book has a lot more to offer. Chapter 8 covers resources in depth sorely missing from most WinForms books. Both embedded and remotely accessed resources are included, as well as the effects of loading them dynamically verses statically.
This is followed by ever enterprise developer's favorite topic, data binding. Much of this based on the Binding object, which "glues" properties together and ensures that any change to one will be reflected in the other.
Binding can be done one single property or an entire object and multiple controls can be bound to the same object. To facilitate binding multiple controls to one object, a DataContext can be used. A DataContext is applied to an element high in the logical tree and affects all the controls beneath it.
Like ASP.NET, templates can be used to facilitate custom presentation of data-bound content. Nathan also covers grouping, sorting, and filtering. One interesting tidbit is how data-binding errors are handled. Instead of throwing an exception, they are silently dumped to the trace listener.
This chapter concludes with advanced techniques for setting up binding sources including XML-based ones.
Chapter 10 covers styles, templates, skins, and themes; everything you need to give an application a custom look while keeping it internally consistent.
Chapters 11 through 14 covers 2D graphics, 3D graphics, Animation, and Audio/Video. While Nathan gives a valiant effort and tries for a lot of depth, these chapters barely scratch the surface and full books on each are in order. Still, it is a good starting point and definitely worth reading.
Hidden in chapter 14 is a section on speech synthesis and recognition. While technically not part of WPF, it can give your applications that extra something. This is followed by a lengthy section on XPS documents. XPS or XML Paper Specification is a subset of XAML specifically designed for presenting static text both on screen and in hardcopy. As the default format for Windows Vista printer drivers, it has some innate advantages over other formats.
This book is both a good introduction to WPF and an excellent resource when looking into advanced topics. In short, it is a must-have for any WPF developer.