1

OK this is stupid! I'm confused. I have this xaml:

    <StackPanel Style="{DynamicResource FormPanel}">
        <StackPanel>
            <Label Content="{DynamicResource Label_FirstName}"
                   Target="{Binding ElementName=FirstName}"/>
            <TextBox x:Name="FirstName" />
        </StackPanel>
        <StackPanel>
            <Label Content="{DynamicResource Label_LastName}"
                   Target="{Binding ElementName=LastName}"/>
            <TextBox x:Name="LastName" />
        </StackPanel>
        <!-- and so one... for each row, I have a StackPanel and a Label and Textbox in it -->
    </StackPanel>

and this style:

<Style x:Key="FormPanel" TargetType="{x:Type StackPanel}">
    <Setter Property="Orientation" Value="Vertical"/>
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Style.Resources>
        <Style TargetType="{x:Type StackPanel}">
            <Setter Property="Orientation" Value="Horizontal" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="Margin" Value="10"/>
            <Style.Resources>
                <Style TargetType="{x:Type Label}">
                    <Setter Property="Width" Value="140"/>
                </Style>
                <Style TargetType="{x:Type TextBox}">
                    <!-- this line doesn't affect -->
                    <Setter Property="HorizontalAlignment" Value="Stretch"/>
                </Style>
            </Style.Resources>
        </Style>
    </Style.Resources>
</Style>

I want to set the TextBox.Width to the rest of container's (StackPanel) width. It seems in this case, HorizontalAlignment = Stretch not works. Have you any idea?

Louis Kottmann
  • 16,268
  • 4
  • 64
  • 88
amiry jd
  • 27,021
  • 30
  • 116
  • 215

2 Answers2

1

StackPanel only allocates space required to child elements than what's available. What you need is a DockPanel.

have a look at This for some detailed explanations on the same topic.

You can modify your code to something like:

<Style x:Key="FormPanel"
        TargetType="{x:Type StackPanel}">
  <Setter Property="Orientation"
          Value="Vertical" />
  <Setter Property="HorizontalAlignment"
          Value="Stretch" />
  <Style.Resources>
    <Style TargetType="{x:Type DockPanel}">
      <Setter Property="HorizontalAlignment"
              Value="Stretch" />
      <Setter Property="Margin"
              Value="10" />
      <Setter Property="LastChildFill"
              Value="True" />
      <Style.Resources>
        <Style TargetType="{x:Type Label}">
          <Setter Property="Width"
                  Value="140" />
        </Style>
      </Style.Resources>
    </Style>
  </Style.Resources>
</Style>

usage:

<StackPanel Style="{DynamicResource FormPanel}">
  <DockPanel>
    <Label Content="{DynamicResource Label_FirstName}"
            Target="{Binding ElementName=FirstName}" />
    <TextBox x:Name="FirstName" />
  </DockPanel>
  <DockPanel>
    <Label Content="{DynamicResource Label_LastName}"
            Target="{Binding ElementName=LastName}" />
    <TextBox x:Name="LastName" />
  </DockPanel>
  <!--  and so one... for each row, I have a StackPanel and a Label and Textbox in it  -->
</StackPanel>

Misc:

in your case I'd probably not do this though. if your use case is to have N rows with each having 2 columns where second column stretches to use all remaining space, rather than have a StackPanel with a bunch of DockPanel's inside it per row, you can do it all with just using a Grid.

something like:

<Grid Margin="5">
  <Grid.Resources>
    <Style TargetType="{x:Type Label}">
      <Setter Property="Margin"
              Value="5" />
    </Style>
    <Style TargetType="{x:Type TextBox}">
      <Setter Property="Margin"
              Value="5" />
    </Style>
  </Grid.Resources>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="140" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Label Grid.Row="0"
          Grid.Column="0"
          Content="{DynamicResource Label_FirstName}"
          Target="{Binding ElementName=FirstName}" />
  <TextBox x:Name="FirstName"
            Grid.Row="0"
            Grid.Column="1" />
  <Label Grid.Row="1"
          Grid.Column="0"
          Content="{DynamicResource Label_LastName}"
          Target="{Binding ElementName=LastName}" />
  <TextBox x:Name="LastName"
            Grid.Row="1"
            Grid.Column="1" />
</Grid>

would give you the same output with only 1 layout container used.

Community
  • 1
  • 1
Viv
  • 17,170
  • 4
  • 51
  • 71
  • @Javad_Amiry I've edited my answer with a "Misc" section which might be better for your use case if it applies directly. Just saves you from not having too many layout containers when you can do what you need with just one. – Viv May 29 '13 at 13:58
  • Well, the form has many rows -which the question example shows only 2 of them- and I have to define a lot of `RowDefinition`s. Also, I have to set `Grid.Row` and `Grid.Column` for each control, which means if I want to reposition a row, I have to change many controls position. But I'm agree with you, `Grid` seems a better container. Do have any idea for above problems I mentioned? – amiry jd May 29 '13 at 16:46
  • @Javad_Amiry if you have quite a lot of rows(say more than 4) I'd say try using an `ItemsControl` with a Template for each item containing the `DockPanel` we had before. This would make it completely dynamic for the rows you have. since you pretty much just define the template and at runtime have the elements rendered accordingly. – Viv May 29 '13 at 16:51
  • @Javad_Amiry you can also have a look at @Rachel 's http://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/ `GridHelper` to help with dynamic `Grid`'s – Viv May 29 '13 at 16:53
0

StackPanel will only be as big as its contents.

I recommend you replace the inner StackPanel with DockPanel. The last child of DockPanel will fill available space (unless you explicitly override that behavior).

Jay
  • 56,361
  • 10
  • 99
  • 123