3.2. StackPanel Controls
While Grid controls provide an open and flexible container inside which controls can be placed in virtually any way required, StackPanel
controls take a different approach to organizing their contained
controls. Instead of allowing controls to be placed in arbitrary
arrangements, they instead allow an ordered series of controls to be
arranged in a single row or column. If a control is added to the middle
of this list of controls, all subsequent controls will be pushed out of
the way to make space. If a stacked control's visibility is toggled or
its size is changed, all the subsequent controls will be pushed or
pulled around to fill the available space.
This control can be useful for creating pages or
areas that consist of repeating items placed either one above or next
to each other. Another useful example is for placement within a ListBoxItem
object: if you want to have images displayed as part of each list item,
or if you need each item to have an associated check box, you can
create a horizontally orientated StackPanel as the Content for each list item, and place the Image, CheckBox, and TextBlock controls inside to facilitate the required functionality.
As always, you can add controls to the StackPanel
either by drawing them from the Toolbox or by adding them directly in
the XAML editor. If you use the Toolbox, the page designer will display
a horizontal or vertical bar above, below, or between the existing
items to indicate to you where your new control will be inserted. This
can be seen in Figure 17,
where a control at the mouse cursor's current location will be added
between the first and second buttons. The same indicator appears if a
control is dragged over a StackPanel, indicating what its position would be if it were dropped at that location.
Controls can be added directly as XAML elements,
too. The order in which the controls are present in the XAML dictates
the order in which they will be stacked on the page.
The only significant new property offered by the StackPanel is its Orientation. When set to its default value of Vertical, the controls will be stacked one above another, as in Figure 17. If the value is changed to Horizontal, the controls will stack from left to right instead.
3.3. Canvas Controls
The next layout control that we will look at is the Canvas
control. The purpose of this container control is to allow objects
placed within it to be positioned absolutely using a simple (x, y)
coordinate system. Whereas the other containers we have looked at have
taken control alignment and margins into consideration, all controls
placed within a Canvas need to know is where they are positioned relative to the top-left corner of the Canvas itself.
Just as controls placed into a Grid can set the Grid.Row and Grid.Column properties as part of their own element declaration, so controls placed into a Canvas can set its Canvas.Left and Canvas.Top properties to specify their positions. They will then appear at exactly the requested location, sized per their own Width and Height properties.
One other detail to be aware of with the Canvas control is that, unlike other container controls, objects that do not properly fit into the Canvas will "overflow" outside of the Canvas
area. The control acts like this for performance reasons; because it is
frequently used to contain animated and moving objects, it is quicker
for it to simply render all its content rather than to have to clip
them into its own area.
If this should present an issue, you can work around it by using the Canvas control's Clip property. By applying a rectangular clipping area that exactly matches the size of the Canvas, anything that falls outside of that area will be clipped and obscured from view. Listing 14 shows an example. The Canvas contains a Rectangle control that is partly outside of its own area. The Canvas.Clip property is set to prevent the overflowing parts of the Rectangle from being displayed. Remember, though, that you will get better performance with clipping disabled.
Example 14. Clipping the contents of a Canvas
<Canvas Width="300" Height="200" Background="Gray"> <Canvas.Clip> <RectangleGeometry Rect="0 0 300 200" /> </Canvas.Clip> <Rectangle Canvas.Left="250" Canvas.Top="150" Height="100" Width="100" Fill="OrangeRed" /> </Canvas>
|
Figure 18 shows the results both without the clipping region on the left, and with it on the right. In both cases, the Canvas itself is shown with a light gray background, and the rectangle is shown with a dark gray background.