I am trying to achieve a certain resizing behavior in the footer of an application, which has the following general xaml structure:
<Window>
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
...
<Grid Grid.Row="3" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" VerticalContentAlignment="Center" VerticalAlignment="Center" Padding="2,0" Content="Checkbox" />
<TextBlock Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center" Text="Log Folder: " />
<TextBox Grid.Column="2" Height="24" VerticalAlignment="Center" VerticalContentAlignment="Center" Padding="2" Focusable="False" IsReadOnly="True" Cursor="Hand" Text="{Binding LogFolder}" />
<Button Grid.Column="3" Height="24" Width="24" Margin="4,0" VerticalAlignment="Center" Command="{Binding SelectFolderCommand}">
<Button.Content>
<Image Width="16" Height="16" Source="/Images/Refresh.png" />
</Button.Content>
</Button>
<Button Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Right" Content=" Button " />
</Grid>
</Grid>
</Window>
In the footer, the text box is truncated if there isn't enough horizontal space to display the whole path:
When there is more than enough space, the text box expands horizontally to fill the available space:
While the former behavior is desired, I would like the text box to not expand to fill the entire available space in the latter case. Rather, I would like the text box to expand just enough to display the entire path, and then have the left button remain adjacent to it, with any excess space appearing between the two buttons, like in this mock-up:
I've tried wrapping the text box and left button in a nested grid like this:
<Grid Grid.Row="3" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" VerticalContentAlignment="Center" VerticalAlignment="Center" Padding="2,0" Content="Checkbox" />
<TextBlock Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center" Text="Log Folder: " />
<Grid Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Height="24" VerticalAlignment="Center" VerticalContentAlignment="Center" Padding="2" Focusable="False" IsReadOnly="True" Cursor="Hand" Text="{Binding LogFolder}" />
<Button Grid.Column="1" Height="24" Width="24" Margin="4,0" HorizontalAlignment="Left" VerticalAlignment="Center" Command="{Binding SelectFolderCommand}">
<Button.Content>
<Image Width="16" Height="16" Source="/Images/Refresh.png" />
</Button.Content>
</Button>
</Grid>
<Button Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Right" Content=" Button " />
</Grid>
While this does achieve the desired behavior when there is more than enough space, when there isn't enough space the left button is overrun:
Beyond this, I've tried numerous other permutations of swapping the Auto
and *
widths for the Grids' columns, wrapping things in StackPanels, docking things in DockPanels, and adding further Grids, but I can only ever achieve one of the two previously described sets of behavior. I.e. either the left button doesn't get overrun when the window is narrow but the text box expands without bound when the window is wide, or the text box's expansion is bounded when the window is wide but the left button gets overrun when the window is narrow.
Is the behavior I'm looking for achievable? Pure-xaml answers preferred, but if I can only achieve this via code in the codebehind, the viewmodel, or a converter, so be it.
Nested Grids as you already have will work as expected.
You just have to make sure to set HorizontalAlignment="Left"
on the inner Grid, and use column widths *
and Auto
in that order.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Content="Checkbox" Padding="2,0"
VerticalAlignment="Center" VerticalContentAlignment="Center" />
<TextBlock Grid.Column="1" Margin="10,0,0,0"
VerticalAlignment="Center" Text="Log Folder: " />
<Grid Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Height="24" Padding="2"
VerticalContentAlignment="Center" Focusable="False"
IsReadOnly="True" Cursor="Hand" Text="{Binding LogFolder}" />
<Button Grid.Column="1" Height="24" Width="24" Margin="4,0"
Command="{Binding SelectFolderCommand}">
<Image Width="16" Height="16" Source="/Images/Refresh.png" />
</Button>
</Grid>
<Button Grid.Column="3" VerticalAlignment="Center" Content=" Button " />
</Grid>