To finish Part I, “Background,” and before moving on to the really fun topics, it’s helpful to examine some of the main concepts that WPF introduces above and beyond what .NET programmers are already familiar with. The topics in this chapter are some of the main culprits responsible for WPF’s notoriously steep learning curve. By familiarizing yourself with these concepts now, you’ll be able to approach the rest of this book (or any other WPF documentation) with confidence.
Some of this chapter’s concepts are unique to WPF (such as logical and visual trees), but others are just extensions of concepts that should be quite familiar (such as properties). As you learn about each one, you’ll see how to apply it to a very simple piece of user interface that most programs need—an About dialog.
A Tour of the Class Hierarchy
WPF’s classes have a very deep inheritance hierarchy, so it can be hard to get your head wrapped around the significance of various classes and their relationships. A handful of classes are fundamental to the inner workings of WPF and deserve a quick explanation before we get any further in the book. Figure 3.1 shows these important classes and their relationships.
FIGURE 3.1. The core classes that form the foundation of WPF.
These 12 classes have the following significance:
- Object—The base class for all .NET classes and the only class in the figure that isn’t WPF specific.
- DispatcherObject—The base class meant for any object that wishes to be accessed only on the thread that created it. Most WPF classes derive from DispatcherObject and are therefore inherently thread-unsafe. The Dispatcher part of the name refers to WPF’s version of a Win32-like message loop, discussed further in Chapter 7, “Structuring and Deploying an Application.”
- DependencyObject—The base class for any object that can support dependency properties, one of the main topics in this chapter.
- Freezable—The base class for objects that can be “frozen” into a read-only state for performance reasons. Freezables, once frozen, can be safely shared among multiple threads, unlike all other DispatcherObjects. Frozen objects can never be unfrozen, but you can clone them to create unfrozen copies. Most Freezables are graphics primitives such as brushes, pens, and geometries or animation classes.
- Visual—The base class for all objects that have their own 2D visual representation. Visuals are discussed in depth in Chapter 15, “2D Graphics.”
- UIElement—The base class for all 2D visual objects with support for routed events, command binding, layout, and focus. These features are discussed in Chapter 5, “Layout with Panels,” and Chapter 6, “Input Events: Keyboard, Mouse, Stylus, and Touch.”
- Visual3D—The base class for all objects that have their own 3D visual representation. Visual3Ds are discussed in depth in Chapter 16, “3D Graphics.”
- UIElement3D—The base class for all 3D visual objects with support for routed events, command binding, and focus, also discussed in Chapter 16.
- ContentElement—A base class similar to UIElement but for document-related pieces of content that don’t have rendering behavior on their own. Instead, ContentElements are hosted in a Visual-derived class to be rendered on the screen. Each ContentElement often requires multiple Visuals to render correctly (spanning lines, columns, and pages).
- FrameworkElement—The base class that adds support for styles, data binding, resources, and a few common mechanisms for controls, such as tooltips and context menus.
- FrameworkContentElement—The analog to FrameworkElement for content. Chapter 11, “Images, Text, and Other Controls,” examines the FrameworkContentElements in WPF.
- Control—The base class for familiar controls such as Button, ListBox, and StatusBar. Control adds many properties to its FrameworkElement base class, such as Foreground, Background, and FontSize, as well as the ability to be completely restyled. Part III, “Controls,” examines WPF’s controls in depth.
Throughout the book, the simple term element is used to refer to an object that derives from UIElement or FrameworkElement, and sometimes ContentElement or FrameworkContentElement. The distinction between UIElement and FrameworkElement or between ContentElement and FrameworkContentElement is not important because WPF doesn’t ship any other public subclasses of UIElement and ContentElement.