One of the more impressive pieces of DirectX is Direct3D, a high-performance three-dimensional drawing engine. And when I say "high-performance," I mean it. By using Direct3D, my 1.83 GHz dual-core laptop can draw tens of thousands of textured triangles moving in real time.
WPF uses Direct3D to make drawing three-dimensional scenes relatively easy. Drawing a scene with Direct3D using code is pretty complicated. WPF provides objects that simplify drawing considerably, although it's still complicated.
One big weakness in Direct3D is that it requires you to figure out what graphics hardware the user has and take best advantage of it. Direct3D forces you to handle a bunch of unusual special cases (for example, if the graphics device becomes unavailable) and makes you build some complicated data structures.
|Figure 4. Cubist Art: WPF objects make drawing three-dimensional scenes easy...well...easier at any rate.|
With WPF you still need to build the data structures (they define the scene, after all) but WPF handles the setup and special cases for you. There seems to be a bit of a performance penalty but at least WPF makes this all easier.
shows a relatively simple program displaying a cube that has brick- and wood-textured surfaces. The program supplies horizontal and vertical scroll bars so users can change the viewing angle. Moving the scroll bars rotates the viewing camera around the X and Y axes by angles that bound to the scroll bars' Value
Unfortunately building three-dimensional models by hand is quite tedious and complex. For example, drawing the cube shown in Figure 4
took 358 lines of XAML code so it's not shown here. You can download the example program and experiment with it if you like.
In Windows Forms graphics, you have two main choices for drawing something: either redraw it during a Paint event or draw it into a bitmap and then display the bitmap. In the first case, you need to redraw frequently, keeping track of whatever it is that you're drawing. If parts of the drawing move over time, you need to keep track of where they all are during every redraw.
In retained-mode graphics, you define objects that represent parts of the drawing: lines, ellipses, text, images, and so forth. WPF automatically redraws any of them that need redrawing when they need it.
If you need one of the objects to move, you simply move it at the appropriate time. WPF automatically redraws the object in its new position as needed. Alternatively, you can define a WPF animation and let WPF move the object over time. Furthermore, because the objects draw themselves as needed, you can zoom in on them and they will redraw themselves with high precision, not the blocky appearance you would get from magnifying a bitmap.
Separate UI and Code-Behind
Using XAML to design a user interface and then writing separate code-behind files lets you distribute the work between user interface designers and VS programmers. Microsoft touts this as one of the great features of WPF—and if you have both designers and developers it is
a great benefit, but it's not a completely new concept. VS has allowed you to separate the user interface from code for years. The earliest versions of VS kept the user interface-building data and the code behind it in separate sections of the same file. You could let different developers work on different copies of this file and then paste them together later, although the process is a bit awkward.
Microsoft also advertises the declarative nature of XAML as one of its big benefits but they don't say why that is a benefit. In some sense it seems reasonable that you should be able to specify a user interface that more or less just sits there using a declarative language that also just sits there.
However, when you throw in all the dynamic linking and animation that WPF supports, it's clear that the user interface does a lot more than just sit there.
At some point, an interface can become so complicated that you're practically forced to build it using a designer such as Expression Blend or VS rather than writing it in plain XAML. At that point, does it matter whether the interface is written in a purely declarative language or whether it's stored as a series of commands for the program to automatically execute when it starts? In either case, your job is done after you design the user interface. You don't need to write code to actually create it.
Declarative programming may be nice but when you're using designers to build the interface anyway it's a moot point.
Content Can Mean "Anything"
Many Windows Forms controls have a property that determines what they display. For example, Labels, TextBoxes, and Buttons all have a Text
property. That property can hold text and nothing else.
In contrast, WPF controls typically have a special "content" property that determines what they contain. For a simple control such as a Label, this might just be some text. For a more complicated control such as a Grid or a StackPanel, the content might include a collection of child controls.
In fact, many WPF controls can contain all sorts of unexpected things in their content properties. For example, a Label typically contains a short piece of text—but you could just as easily fill it with a StackPanel holding an Image and another Label. (This would be an odd use for a Label but you could
do it if you had the need.)
The following XAML code builds a button that contains a StackPanel, which holds an Image and a TextBlock. While the result looks different from a normal Button, it behaves exactly like a Button should.
|Figure 5. Creative Content: A control's content property can contain just about anything.|
<Button Height="120" Width="250" Margin="10,10,10,10">
<StackPanel Width="216" Height="100" Orientation="Horizontal">
<Image Width="100" Height="100" Source="Cat.jpg"
<TextBlock Text="Click here if you're a cat person."
TextWrapping="Wrap" Width="120" Margin="2,2,2,2"/>
shows the sample GridInButton
program displaying three buttons that don't hold just plain text. The first two contain a StackPanel holding an Image and a TextBlock. The third holds a Grid with background set to a spider web picture, holding a TextBlock and six small pictures. All the buttons behave just like normal buttons.
WPF comes with several new controls for arranging content, including:
- StackPanel (arranges children in a single row or column)
- DockPanel (docks children to its edges)
- WrapPanel (arranges children in a row/column and wraps to a new row/column when it must)
- Grid (arranges children in rows and columns very flexibly)
Although the names may be unfamiliar, you'll recognize some of these immediately, because they've been around for a while. For example, the (old) FlowLayoutPanel control does roughly what the (new) WrapPanel does and the (old) TableLayoutPanel serves a purpose similar to that of the (new) Grid control.
Some developers go on to say that these new controls change the way you design interfaces, and that using them you can allow the controls to take best advantage of the available space as a window resizes. However, good developers have already been doing that for years using arranging controls such as FlowLayoutPanel, and the Anchor
properties. So, the new controls are not strictly necessary for you to make full use of the available space but they do give you some new options.