Using a WPF StackPanel for Business Forms

In WPF if you want to layout a typical business form like the one shown in Figure 1, most people would use a Grid control with rows and columns. However, you may also use a StackPanel control. While sometimes you might need the re-sizing capabilities of a Grid, you sometimes just need a fixed size. For a fixed-size form a StackPanel control can be a little easier and offers a little more flexibility.

StackPanel Layout 

Figure 1: A business form using a StackPanel

Using a Grid
If you were to layout the above form using a Grid control you might write code that looks like the following:

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Label   Grid.Column="0" Grid.Row="0">FirstName</Label>
  <TextBox Grid.Column="1" Grid.Row="0" Name="txtFirst" />
  <Label   Grid.Column="0" Grid.Row="1">Last Name</Label>
  <TextBox Grid.Column="1" Grid.Row="1" Name="txtLast" />
  <Button  Grid.Column="1" Grid.Row="2" Name="btnClose">
    Close
  </Button>
</Grid>

In the above XAML code you need to assign the Grid.Row and a Grid.Column properties on each Label, TextBox and Button control. This is how the XAML knows where to place each control in the Grid.

Using a StackPanel Control
Now, let’s layout the same form using a series of StackPanel controls. Each StackPanel for each “row” will have the Orientation set to “Horizontal”. There will also be a Style setup for each Label to set the Width property to a specific amount so each text box will be aligned correctly. Below is what the form that uses the StackPanel looks like.

<StackPanel>
  <StackPanel Orientation="Horizontal">
    <Label>First Name</Label>
    <TextBox Name="txtFirst"></TextBox>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <Label>Last Name</Label>
    <TextBox Name="txtLast"></TextBox>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <Label></Label>
    <Button Name="btnClose">Close</Button>
  </StackPanel>
</StackPanel>

Now here are the styles that you add to the Window.Resources on this window to give the form its structure.

<Window.Resources>
  <Style TargetType="Label">
    <Setter Property="Width" Value="100" />
  </Style>
  <Style TargetType="TextBox">
    <Setter Property="MinWidth" Value="160" />
  </Style>
</Window.Resources>

Now, there are advantages and disadvantages to using a Grid and to using a StackPanel. A Grid is great because the text box controls will automatically re-size as the user sizes the form. However, if you have several rows and you wish to insert a row in the middle, you need to renumber each row after the new row. Sometimes the VS.NET designer will renumber them for you, but sometimes it won’t. Or, if you wish to move an existing row below or above another, you will also be doing a lot of manual renumbering.

Many business forms do not require re-sizing, so in this case a StackPanel works very well. Using styles gives you the same flexibility as the Grid column definitions, so this is very nice. Also, the ability to just move rows around without worrying about renumbering is a great benefit. However, you do lose the re-sizing capabilities, so this is a tradeoff.

Summary
As with most WPF applications, there are typically more ways than one to accomplish the same thing. This is probably the most frustrating part of learning WPF. Here I showed you a couple different ways to layout the same business form. Each method has its advantages and disadvantages, so it will be up to you to determine when to use each method.

Past Blog Content

Blog Archive

1 Comment

  • If you use a stackpanel outside, and grids with shared size groups inside, you have a little bit of both...
    &lt;Stackpanel&gt;
    &nbsp;&lt;Grid&gt;
    &nbsp; &nbsp;&lt;Grid.ColumnDefinitions&gt;
    &nbsp; &nbsp; &nbsp;&lt;ColumnDefinition SharedSizeGroup="Group1"/&gt;
    &nbsp; &nbsp; &nbsp;&lt;ColumnDefinition SharedSizeGroup="Group2"/&gt;
    &nbsp; &nbsp;&lt;/Grid.ColumnDefinitions&gt;
    &nbsp; &nbsp;&lt;Label&gt;First Name&lt;/Label&gt;
    &nbsp; &nbsp;&lt;TextBox Name="txtFirst"&gt;&lt;/TextBox&gt;
    &nbsp;&lt;/Grid&gt;
    &lt;/Stackpanel&gt;
    But of course, it's more xaml.

Comments have been disabled for this content.