4.2. Using Width and AlignmentBy default, XAML renders elements on the screen in the order in which they are defined within the XAML file. If the TextBox in Example 4-2 is added to the StackPanel before the first Label, then it will appear as the first element and the Label will appear after it. By default, all elements have a width equal to the container element of which they are children. Using the login page example from Chapter 3 without specifying any kind of formatting or layout restrictions yields the user interface in Figure 4-6. Figure 4-5. Using DockPanel.Dock to position elementsExample 4-2. Example code for user login screen with no layout or formatting
This is neither aesthetically pleasing nor is it particularly usable. There is no clear delineation between elements, and it is hard on the eyes. The first thing to do is limit the width of the elements to make them easier to read. There are three options to accomplish this: define the Width attribute on all the elements added to the StackPanel, limit the width of the StackPanel itself, or change the HorizontalAlignment of the StackPanel. The second option will force all the elements in the StackPanel to be the same width. While this is a viable option, it may not be appropriate for every situation, especially if you don't want all the elements to be the same width as the TextBox. The best option in this case is to limit the width of each individual element. Note that specifying the Width of an element will change its resizing behavior. When a width is set, the element no longer automatically resizes when its container changes size. Example 4-3 shows how to use Width to constrain the size of an element. Figure 4-6. User login screen with no layout or formattingExample 4-3. Using Width to constrain the size of elements
As you can see from Figure 4-7, it is now possible to clearly delineate between elements, but the result is still not acceptable. The elements are centered on the page when they really should be left-justified. That's easy enoughyou can align elements within a container using the HorizontalAlignment and VerticalAlignment attributes. Alignment can be a tricky subject because there's more than just left, right, and center, and alignment interacts with width in strange and mysterious ways. Traditional alignment values act as you'd expect. StackPanel will align elements on its left edge, its right edge, or centered, based on the value of HorizontalAlignment. The default value for HorizontalAlignment is Stretch. This forces all contained elements to stretch themselves (appropriate, isn't it?) to fill the entire width of the panel. Using a HorizontalAlignment of Stretch and specifying widths on individual elements has interesting effects. In Figure 4-8, the first element added is a border with a width of 200 and a TextBlock. The element's width has been rendered correctly, but it is centered in the panel. Elements in a StackPanel using Stretch as its HorizontalAlignment are positioned centrally in the panel and then stretched equally to the left and right according to their width. In the third element ("I have no width"), you can see that if no width is specified, the element stretches to fill the entire panel. Figure 4-7. Result of using Width to constrain element sizesFigure 4-8. Specifying widths and HorizontalAlignment=StretchThe second element added is a Border with no width, so it appropriately fills the width of the panel, but the TextBlock contained within the Border element has a set width of 100. The TextBlock is therefore centered and stretched equally to the left and right to fill the specified width of 100. When using Stretch, remember that elements are stretched from a center point in the StackPanel, not anchored to the left and stretched across the width of the panel. There are also some odd effects when specifying a width for only one element using alignments other than Stretch. Elements with no width will automatically size themselves to their content or to the size of the element with a specified width, whichever is larger.
Returning to the example interface and applying a Left HorizontalAlignment, as well as specifying widths for the elements, produces Figure 4-9. While this is certainly closer to the original, the elements are still bumping up against one another, and the TextBox and PasswordBox are too close to the left edge of the page. To fine-tune this interface further, you must use the Margin and Padding attributes. Figure 4-9. Result of setting HorizontalAlignment to Left |