views:

566

answers:

7

I have a WPF form, I want to lay out a standard form onto it. Each form element will have a label, and then a control. Pretty standard stuff.

If I use a wrap panel, it can cause the label and the control to be separated, but I want them to stay together. is there some WPF equivalent of nobr?

Grid works, and allows for column spanning etc, however I really really hate that you specify the column and row on each control. This makes it extremely inconvenient to reorder or insert things into the list.

Is there a way to get the grid to use more HTML style column/rows where the items are a child of the row they are in, so that I can re-order easily?

Is there some other control that will let me layout a form easily?

+1  A: 

Try the UniformGrid control.

Rafa Castaneda
+1  A: 

What you might be looking for is a stack panel. Using a vertical StackPanel will allow you to arrange your label and controls consistently. For each label and control you might want a horizontal stack panel like so

<StackPanel Orientation="Vertical">
  <StackPanel Orientation="Horizontal">
     <Label Width="150">Name</Label>
     <Textbox Width="200/>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
     <Label Width="150">Date of Birth</Label>
     <DatePicker Width="200/>
  </StackPanel>
</StackPanel>

Now you can add, remove, edit, and reorder to your heart's content without worrying about columns and rows.

Mike Brown
+1  A: 

is there some WPF equivalent of nobr?

Remember that you can nest panels:

<WrapPanel Orientation="Horizontal">
   <StackPanel Orientation="Horizontal">
      <Label>Some field</Label>
      <TextBox>Some value</TextBox>
   </StackPanel>
   <StackPanel Orientation="Horizontal">
      <Label>Another field</Label>
      <TextBox>Another value</TextBox>
   </StackPanel>
   ...
</WrapPanel>

Also, for columnar layouts, the shared size scope of the Grid can coordinate any number of grids that use it:

<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
         <ColumnDefinition Width="*"/>
      <Grid>
      <Label Grid.Column=0>Some field</Label>
      <TextBox Grid.Column=1>Some value</TextBox>
   </Grid>
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
         <ColumnDefinition Width="*"/>
      <Grid>
      <Label Grid.Column=0>Another field</Label>
      <TextBox Grid.Column=1>Another value</TextBox>
   </Grid>
</StackPanel>

I kind of hate how verbose the XAML for this is, especially that you have to repeat the column definitions. Though if you structure your classes properly and use templates it's not so terrible. And notice that you aren't keep track of row numbers anywhere in this scheme, so reordering fields is simple.

Robert Rossney
A: 

If you can accord it, I recommend Expression Blend if you are going to be doing much UI design. It allows a simpler view of the items. Nesting controls into various containers is a good way to get the UI to be dynamic, but structured.

Typically I will use a Grid panel to break a window up into functional areas. Then I will use a series of StackPanels (often a vertical stack panel with horizontal StackPanels inside it, each with a label and textbox).

Unfortunately Grids only work as you stated. Elements in them specify the row and/or column that they reside in. If you used Blend, adding Grid Columns or Rows will have controls auto-magically change the row/column specification to stay in the position they were placed.

Hope it helps.

Expression Blend Trial at Microsoft.

Cory

OffApps Cory
+1  A: 

Check out Karl's stuff.

http://karlshifflett.wordpress.com/2008/10/23/wpf-silverlight-lob-form-layout-searching-for-a-better-solution/

Simple and clean xaml:

<pt:Form x:Name="formMain" Style="{DynamicResource standardForm}" Grid.Row="1">
  <TextBox pt:FormItem.LabelContent="_First Name" />
  <TextBox pt:FormItem.LabelContent="_Last Name"  />
  <TextBox pt:FormItem.LabelContent="_Phone" Width="150" HorizontalAlignment="Left" />
  <CheckBox pt:FormItem.LabelContent="Is _Active" />    
</pt:Form>
Ray
A: 

In our product we use a HeaderedContentControl to lay out forms in a grid. The control template has a label and padding/margins so that the control's content is always spaced appropriately. In the XAML we just add them down the columns.

I'd post some XAML but I'm in the middle of getting a new computer set up. :| But from what I remember it would look something like this:

<Style x:Key="hccFormStyle" Targettype="{x:Type HeaderedContentControl}>
... some setters for colors, margin, padding, etc...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
  <Label Content={Binding Content} Target={Binding Tag}> <-- pass the control for the access key with the tag
  <ContentPresenter>
</ControlTemplate>
...triggers if necessary - hover states, etc...
</style>

Then in the grid, you define your rows and columns, and put one of these in each cell, or just down each row:

<HeaderedContentControl x:Name="username" Grid.Column=0 Content="User Name" Tag=textboxUserName>
 <Textbox x:Name=textboxUserName>
</HeaderedContentControl>

I might be answering a different question but this is how we lay out our forms.

dex3703
A: 

I had the same problem, reordering controls in a Grid based layout is a real pain.

So I've wrote a custom panel that does "form layout" (groups of two columns, all labels same size, all control same size,everything aligned, etc.), it's on my blog at: http://www.nbdtech.com/Blog/archive/2010/07/27/easy-form-layout-in-wpf-part-1-ndash-introducing-formpanel.aspx

Nir