Nikola Novak
Nikola Novak

Reputation: 4462

How to make TextBox fill all available space without later resizing to its content?

I have the following Grid with a TextBox in it:

<UserControl ...>
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition Height="30px"/>
   <RowDefinition Height="Auto"/>
   <RowDefinition Height="Auto"/>
   <RowDefinition Height="1px"/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
   <ColumnDefinition Width="Auto"/>
   <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  <TextBox Grid.Column="1" Grid.RowSpan="3" AcceptsReturn="True"
   TextWrapping="Wrap" HorizontalScrollBarVisibility="Hidden"
   VerticalScrollBarVisibility="Visible" HorizontalAlignment="Stretch"
   VerticalAlignment="Stretch"/>
  <!-- content in other cells of the Grid's first column -->
 </Grid>
</UserControl>

I want the TextBox to fill all space that is available on the control (width and height-wise) and should the user enter more text than fits into it I want its vertical scrollbar to become active, without resizing the TextBox. What happens instead is that the size of the TextBox changes to accomodate the content and the whole grid grows with it.

How do I achieve what I need?

Edit: Here's an illustration of what happens. Two screenshots of the same <code>UserControl</code> with different content in <code>TextBox</code>.

The above screenshot is of the situation when the content fits comfortably into the TextBox. The below screenshot is of the situation when there is not enough room to fit all content - the TextBox is then resized to fit it and this resizes also the grid that it is placed in, making it look broken.

Edit 2: The project that demonstrates this behavior is here.

Upvotes: 1

Views: 406

Answers (2)

Nikola Novak
Nikola Novak

Reputation: 4462

I have managed to solve this by adding an invisible Border in the same cells of the Grid as the TextBox, then setting TextBox' Width and Height to ActualWidth and ActualHeight of that Border respectively:

<Border x:Name="b" Grid.Column="1" Grid.RowSpan="3"
 HorizontalAlignment="Stretch"/>
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Grid.Column="1"
 Grid.RowSpan="3" Width="{Binding ActualWidth, ElementName=b}"
 Height="{Binding ActualHeight, ElementName=b}"
 HorizontalScrollBarVisibility="Hidden"
 VerticalScrollBarVisibility="Visible" HorizontalAlignment="Stretch"
 VerticalAlignment="Stretch"/>

This then caused the TextBox to stay of fixed Height regardless of its content, but there was another problem with its Width: it grew when the interface was expanded, but didn't shrink afterwards, because of the underlying ScrollViewer. The trick was to set that ScrollViewer's HorizontalScrollBarVisibility to Disabled, instead of Hidden as I had done previously.

I pushed changes of the example project to GitHub, so the solution is now available here.

Upvotes: 1

mm8
mm8

Reputation: 169200

The TextBox doesn't fill the Grid. You can confirm this yourself by specifying a Background for the Grid:

<UserControl>
    <Grid Background="Yellow">
    ...

This is because the height of the Grid is 30 px + whatever the height of the TextBox is + 1 px. For the contents of the row 2 or 3 to fill the Grid, you need to change the Height of at least one of the RowDefinitions to *:

<UserControl>
    <Grid Background="Yellow">
        <Grid.RowDefinitions>
            <RowDefinition Height="30px"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="1px"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="1" Grid.RowSpan="3" AcceptsReturn="True"
                 TextWrapping="Wrap" HorizontalScrollBarVisibility="Hidden"
                 VerticalScrollBarVisibility="Visible" HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch"/>
    </Grid>
</UserControl>

Upvotes: 0

Related Questions