4.1. StackPanel and DockPanel
The two most commonly used Panel subclasses are StackPanel and DockPanel. Both are used for relative positioning of elements and automatically handle placement of elements based on the order in which they are declared.
The differences between the two types of Panel can be summed up as follows:
The concept is best illustrated by recreating the user login interface (from Chapter 3) using both types of panels. The result is shown in Figure 4-1. The elements of this user login interface are each added in the following order:
Figure 4-1. Positioning elements with StackPanel and DockPanel
The StackPanel, indicated by the black-bordered area in Figure 4-1, stacks elements from top to bottom as they are added. The DockPanel, indicated by the lighter-bordered area in Figure 4-1, positions them from left to right as they are added. There is no additional formatting nor any positioning attributes specified, so the default values are active, which gives the interface a very strange look (especially in the DockPanel).
The default Orientation for StackPanel is Vertical, but it can be set to Horizontal. Changing the Orientation of the StackPanel to Horizontal will cause the elements to be stacked from left to right rather than from top to bottom.
DockPanel can be further manipulated in terms of the way elements are stacked within the Panel. For example, elements can be "docked" at the top, which will cause them to expand horizontally to fill the width of the DockPanel. Elements can be docked at the left or right, which will cause them to expand vertically to fill their allocated space and align either their left or right edges with the DockPanel. Elements can also be docked at the bottom, which will cause them to align their bottom edges with the bottom of the DockPanel and expand horizontally to fill their allocated space. Elements use the attached property DockPanel.Dock to determine where they will be docked.
Because elements are rendered in the order in which they are added, using the positioning of DockPanel's properties makes the values relative to the last element added. For example, if the first element added specifies a DockPanel.Dock attribute as Top and the second also declares Top, the second element docks itself at the bottom edge of the first element because that is the top of the layout for the second element. Figure 4-2 illustrates this concept.
Figure 4-2. Effects of specifying DockPanel.Dock="Top"
As you might expect, changing the value of DockPanel.Dock from Top to Bottom for all four elements in Figure 4-2 does not change much but the order. When all elements specify DockPanel.Dock="Bottom", Element #1 appears on the bottom, Element #2 above it, and so on. You can probably guess what happens if all elements specify Left for DockPanel.Dock, as well as Right. Elements are rendered in order from left to right and right to left, respectively.
The real fun begins when you start mixing and matching all four values to rearrange your user interface. For example, specifying Left, Right, Top, and Bottom as DockPanel.Dock values for each of the four elementsin orderresults in a fairly orderly interface, shown in Figure 4-3.
While it's orderly, it may be somewhat of a surprise to see that Element #3 is docked at the top of the screen and does not appear to be docked relative to Element #1. It actually is relative to Element #1 and Element #2, but both these elements have taken up all the layout space on the left and right edges, according to their DockPanel.Dock values. That leaves only the area between the two elements for Element #3 and Element #4 to occupy.
Figure 4-3. Mixing and matching DockPanel.Dock values
If the values of DockPanel.Dock are reversed so that Element #1 specifies Top and Element #2 specifies Bottom, then Element #3 declaring Left will touch the left side of the panel but between Element #1 and Element #2. This leaves Element #4 to declare Right, which positions it against the right edge of the panel, but like Element #3, between Elements #1 and #2. Figure 4-4 shows the results of switching the values.
Figure 4-4. Mixing and matching DockPanel.Dock values again
The last element added will occupy whatever space remains; that's why Element #4 always appears bigger than Element #3, even though intuitively it seems that they should be the same size.
Example 4-1 uses Border elements around the user-login interface elements to illustrate the effects of specifying the attached attribute DockPanel.Dock on elements added to the DockPanel. Figure 4-5 shows the result of evaluating Example 4-1 with XamlPad.
Example 4-1. Using DockPanel.Dock to position elements
This user-login interface isn't looking quite like it should, however, even when using a DockPanel to position elements. StackPanel and DockPanel are useful for the general positioning of elements, but to fine-tune the layout of a user interface, you must specify additional attributes such as Width and Alignment.