Canvas
Occasionally, the automatic layout offered by DockPanel,
StackPanel, or Grid will not enable the look you require, and
it will be necessary to take complete control of the precise positioning of
every element. For example, when you want to build an image out of graphical
elements the positioning of the elements is dictated by the picture you are
creating, not by any set of automated layout rules. For these scenarios, you
will want to use the Canvas.
The Canvas is the simplest of the panels. It allows the
location of child elements to be specified precisely relative to the edges of
the canvas. The Canvas doesn't really do any layout at allit simply
puts things where you tell it to.
 |
If you are accustomed to working with fixed layout
systems such as those offered by Visual Basic 6, MFC, and the most basic way of
using Windows Forms, then the Canvas will seem familiar and natural.
However, it is strongly recommended that you avoid it unless you really need
this absolute control. The automatic layout provided by the other panels will
make your life very much easier, because they can adapt to changes in text and
font. They also make it far simpler to produce resizable user interfaces.
Moreover, localization tends to be much easier with resizable user interfaces,
because different languages tend to produce strings with substantially
different lengths. Don't opt for the Canvas simply because it seems
familiar.
|
|
When using a Canvas, you must specify the location of
each child element. If you don't, all of your elements will end up at the top
left-hand corner. Canvas defines four attached properties for setting
the position of child elements. Vertical position is set with either the Top
or Bottom property, and horizontal position is determined by either
the Left or Right property, an approach that is illustrated
in Example 2-16.
Example 2-16. Positioning on a Canvas
<Canvas Background="Yellow">
<TextBlock Canvas.Left="10" Canvas.Top="20">Hello</TextBlock>
<TextBlock Canvas.Right="10" Canvas.Bottom="20">world!</TextBlock>
</Canvas>
Example 2-16 shows
a Canvas containing two TextBlock elements. The first has
been positioned relative to the top-left corner of the Canvas: the
text will always appear ten pixels in from the left and twenty pixels down from
the top. (As always, these are logical pixelsnominally 1/96th
of an inch, and not necessarily a single screen pixel.)
Figure 2-23 shows the result.
The second text element is more interesting. It has been
positioned relative to the bottom right of the form, which means that if the
canvas gets resized, the element will move with that corner of the canvas. For
example, if the Canvas were the main element of a window, the second TextBlock
element would move with the bottom right corner of the window if the user
resized it.
 |
If you have used Windows Forms, you may be
wondering whether setting both the Top and Bottom properties
(or both Left and Right properties) will cause the element to
resize automatically when the containing canvas is resized. Sadly, unlike with
anchoring in Windows Forms, this technique does not work. If you specify both Left
and Right, or both Top and Bottom, one of the
properties will simply be ignored. (Top takes precedence over Bottom,
and Left takes precedence over Right.)
Fortunately, it is easy to get this kind of behavior with a
single-cell Grid and the Margin property. If you put an
element into a grid with a margin of, say, "10,10,30,40" its top-left corner
will be at (10,10) relative to the top left of the grid, its right-hand side
will always be 30 pixels from the right edge of the grid, and its bottom edge
will always be 40 pixels from the bottom of the grid. So this is another reason
to prefer Grid over Canvas.
|
|
The main use for Canvas is to arrange drawings. If you
employ graphical elements such as Ellipse
and Path, which are discussed in
Chapter 7, you will typically need precise control over their location,
in which case the Canvas is ideal.
When child elements are larger than their parent panel, most
panels crop them, but the Canvas does not by default. This is
sometimes useful because it means you do not need to specify the size of the
canvasa zero-sized canvas works perfectly well. However, if you want to clip
the content, set ClipToBounds to TRue.
The price you pay for the precise control offered by the Canvas
is inflexibility. However, there is one common scenario in which you can
mitigate this rigidity. If you've used a Canvas to arrange a drawing,
and would like that drawing to be automatically resizable, you can use a Viewbox
in conjunction with the Canvas.
|