Home > Articles > Operating Systems, Server > Microsoft Windows Desktop

  • Print
  • + Share This
This chapter is from the book

Controlling Position

This section doesn’t discuss positioning elements with (X,Y) coordinates, as you might expect. Parent panels define their own unique mechanisms for enabling children to position themselves, and those are discussed in the next hour. A few mechanisms are common to all FrameworkElement children, however, and that’s what this section examines. These mechanisms are related to alignment and a concept called flow direction.

Alignment

The HorizontalAlignment and VerticalAlignment properties enable an element to control what it does with any extra space that its parent panel gives it. Each property has a corresponding enumeration with the same name, giving the following options:

  • HorizontalAlignmentLeft, Center, Right, and Stretch
  • VerticalAlignmentTop, Center, Bottom, and Stretch

Stretch is the default value for both properties, although various controls override the setting. The effects of HorizontalAlignment can easily be seen by placing a few Buttons in a StackPanel (a panel described further in the next hour) and marking them with each value from the enumeration:

<StackPanel>

  <Button HorizontalAlignment ="Left" Content ="Left" Background="Red"/>

  <Button HorizontalAlignment ="Center" Content ="Center" Background="Orange"/>

  <Button HorizontalAlignment ="Right" Content ="Right" Background="Green"/>

  <Button HorizontalAlignment ="Stretch" Content ="Stretch" Background="Blue"/>

</StackPanel>

Notice that an enumeration value such as HorizontalAlignment.Left is able to be specified in XAML as simply Left. This is thanks to a type converter that is able to handle any enumeration. The rendered result appears in Figure 3.2.

Figure 3.2

Figure 3.2 The effects of HorizontalAlignment on Buttons in a StackPanel

These two properties are useful only when a parent panel gives the child element more space than it needs. For example, adding VerticalAlignment values to elements in the StackPanel used in Figure 3.2 would make no difference, because each element is already given the exact amount of height it needs (no more, no less).

Content Alignment

In addition to HorizontalAlignment and VerticalAlignment properties, the Control class also has HorizontalContentAlignment and VerticalContentAlignment properties. These properties determine how a control’s content fills the space within the control. (Therefore, the relationship between alignment and content alignment is somewhat like the relationship between Margin and Padding.)

The content alignment properties are of the same enumeration types as the corresponding alignment properties, so they provide the same options. However, the default value for HorizontalContentAlignment is Left, and the default value for VerticalContentAlignment is Top. Some elements implicitly choose different defaults. Buttons, for example, center their content in both dimensions by default.

Figure 3.3 demonstrates the effects of HorizontalContentAlignment, simply by taking the previous XAML snippet and changing the property name as follows:

<StackPanel>
  <Button HorizontalContentAlignment="Left" HorizontalAlignment="Stretch"
          Content="Left" Background="Red"/>
  <Button HorizontalContentAlignment="Center" HorizontalAlignment="Stretch"
          Content="Center" Background="Orange"/>
  <Button HorizontalContentAlignment="Right" HorizontalAlignment="Stretch"
          Content="Right" Background="Green"/>
  <Button HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch"
          Content="Stretch" Background="Blue"/>
</StackPanel>
Figure 3.3

Figure 3.3 The effects of HorizontalContentAlignment on Buttons in a StackPanel

Each Button also has its HorizontalAlignment set to Stretch rather than its default of Left so the differences in HorizontalContentAlignment are visible. Without this, each Button would auto-size to its content and there would be no extra space for the content to move within.

In Figure 3.3, the Button with HorizontalContentAlignment="Stretch" might not appear as you expected. Its inner TextBlock is technically stretched, but it’s meaningless because TextBlock (which is not a Control) doesn’t have the same notion for stretching its inner text. For other types of content, Stretch can indeed have the intended effect.

FlowDirection

FlowDirection is a property on FrameworkElement (and several other classes) that can reverse the way an element’s inner content flows. It applies to some panels and their arrangement of children, and it also applies to the way content is aligned inside child controls. The property is of type FlowDirection, with two values: LeftToRight (FrameworkElement’s default) and RightToLeft.

The idea of FlowDirection is that it should be set to RightToLeft when the current culture corresponds to a language that is read from right to left. This reverses the meaning of left and right for settings such as content alignment. The following XAML demonstrates this, with Buttons that force their content alignment to Top and Left but then apply each of the two FlowDirection values:

<StackPanel>
  <Button FlowDirection="LeftToRight"
          HorizontalContentAlignment="Left" Width="320"
          Background="Red">LeftToRight</Button>
  <Button FlowDirection="RightToLeft"
          HorizontalContentAlignment="Left" Width="320"
          Background="Orange">RightToLeft</Button>
</StackPanel>

The result is shown in Figure 3.4.

Figure 3.4

Figure 3.4 The effects of FlowDirection on Buttons with Left content alignment

Notice that FlowDirection does not affect the flow of letters within these Buttons. English letters always flow left to right, and Arabic letters always flow right to left, for example. But FlowDirection reverses the notion of left and right for other pieces of the user interface, which typically need to match the flow direction of letters.

You must explicitly set FlowDirection to match the current culture, but fortunately you can do this on a single, top-level element. Windows doesn’t automatically change FlowDirection on your behalf in order for the behavior to be predictable and easily testable. The idea is that you should specify FlowDirection appropriately inside the .resw file for each distinct culture you support. For example, if you include a resource with the name Root.FlowDirection, then you can mark a Page’s root element with x:Uid="Root" to control FlowDirection on a per-culture basis. The resource just needs to be given the value of LeftToRight or RightToLeft.

  • + Share This
  • 🔖 Save To Your Account