Content Model
While the different kinds of WPF application styles are
interesting, the core of any presentation framework is in the presentation
elements themselves. Fundamentally, we have "bits of content and behavior" and
"containers of bits of content and behavior." We've already seen both kinds;
e.g., a Button is a control, providing
content and behavior and a Window is a
container. There are two things that may surprise you about content containment
in WPF, however.
The first is that you don't need to put a string as the content
of a Button; it will take any .NET object. For example, you've already seen a
string as a button's content, which looks like
Figure 1-9, created with the code in
Example 1-19.
Example 1-19. A button with string content
<Window ...>
<Button Width="100" Height="100">Hi</Button>
</Window>
However, you can also use an image, as in
Figure 1-10 and implemented in
Example 1-20.
Example 1-20. A button with image content
<Window ...>
<Button Width="100" Height="100">
<Image Source="tom.png" />
</Button>
</Window>
You can even use an arbitrary control, like a TextBox,
as shown in Figure 1-11 and
implemented in Example 1-21.
Example 1-21. A button with control content
<Window ...>
<Button Width="100" Height="100">
<TextBox Width="75">edit me</TextBox>
</Button>
</Window>
Further, as you'll see in
Chapters 2 and 5,
you can get fancy and show a collection of nested elements in a Button
or even use nonvisual objects as the content of a Button. The reason
that the Button can take any object as content is because it's derived
ultimately from a class called ContentControl, as are many other WPF
classese.g., Label, ListBoxItem, ToolTip, CheckBox,
RadioButton and, in fact, Window itself.
A ContentControl knows how to hold anything that's able
to be rendered, not just a string. A ContentControl gets its content
from the Content property, so you could specify a Button's
content like so (this is the longhand version of
Example 1-19):
<Button Width="100" Height="100" Content="Hi" />
ContentControls are especially useful, because you get
all of the behavior of the "thing,"e.g., Button, Window, or ListBoxItembut
you can display whatever you like in it without having to build yourself a
special classe.g., ImageButton, TextBoxListBoxItem, etc.
1.3.1. XAML Property-Element Syntax
Still, while setting the Content property as a string
attribute in XAML works just fine for specifying a string as content, it
doesn't work at all well for specifying an object as content, such as in the
image example. For this reason, XAML defines the property-element
syntax, which uses nested Element.Property elements for specifying
objects as property values. Example
1-22 shows the property-element syntax to
set a string as a button's content.
Example 1-22. Property element syntax with a string
<Button Width="100" Height="100">
<Button.Content>Hi</Button.Content>
</Button>
Example 1-23 is
another example using an image:
Example 1-23. Property element syntax with an Image
<Button Width="100" Height="100">
<Button.Content>
<Image Source="tom.png" />
</Button.Content>
</Button>
Since XML attributes can only contain one thing,
property-element syntax is especially useful when you've got more than one
thing to specify. For example, you might imagine a button with a string and an
image, defined in Example 1-24.
Example 1-24. Can't have multiple things in a
ContentControl
<Button Width="100" Height="100">
<!-- WARNING: doesn't work! -->
<Button.Content>
<TextBlock>Tom: </TextBlock>
<Image Source="tom.png" />
</Button.Content>
</Button>
While normally the property-element syntax would be useful for
this kind of thing, in this particular case, it doesn't work at all. This
brings us to the second thing that may surprise you about content containment
in WPF: while Button can take any old thing as content, as can a Window,
both of them can only take a single thing which, without additional
instructions, WPF will center and fill up the element's entire client area. For
more than one content element or a richer layout policy,
you'll need a panel.
 |