Reputation: 27585
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?
Upvotes: 1
Views: 370
Reputation: 17380
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.
Upvotes: 1
Reputation: 57919
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).
Upvotes: 0