Elijah W. Gagne
Elijah W. Gagne

Reputation: 2841

WPF: Layout dynamic content so that there's only a scrollbar if necessary, otherwise content expands to fill space

I'm trying to layout a set of TextBoxes, vertically, one on top of the other. If there are so many TextBoxes that they cannot fit within the Window height then I want a ScrollBar to become available on the Window. The number of input TextBoxes is variable. There is always a last TextBox with the name output.

If all the TextBoxes can appear within the Window height then I want the last TextBox to stretch to the bottom and fill all the remaining space. In addition, if the output TextBox has a lot of Text then I want this TextBox to make a ScrollBar available.

Here's some pseudo XAML of what I have:

<ScrollViewer>
    <Grid>
        <TextBox Name="input1" Margin="12, 12, 12, 12" VerticalAlignment="Top" HorizontalAlignment="Left" />
        <TextBox Name="input2" Margin="12, 60, 12, 12" VerticalAlignment="Top" HorizontalAlignment="Left" />
        <TextBox Name="input3" Margin="12, 108, 12, 12" VerticalAlignment="Top" HorizontalAlignment="Left" />
        ...
        <TextBox Name="inputN" Margin="12, ((N - 1) * 48 + 12), 12, 12" VerticalAlignment="Top" HorizontalAlignment="Left" />
        <TextBox Name="ouput" Margin="12, (N * 48 + 12), 12, 12" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
    </Grid>
</ScrollViewer>

The problem I have right now is that if the output TextBox has a lot of content then it increases in height and has the Window present a ScrollBar. Instead I want the output TextBox to get the ScrollBar.

I can fix that problem by removing the ScrollViewer that is holding the Grid. However if I do that I get another problem. Because the number of input TextBoxes is variable, if there are so many that not all the TextBoxes can show in the Window, the Window doesn't get a ScrollBar, which I need.

I have tried playing around with putting a MaxHeight on the output TextBox, but if there are few input TextBoxes and a tall Window then I'm apt to not fill all of the remaining vertical space.

Upvotes: 1

Views: 1119

Answers (2)

NestorArturo
NestorArturo

Reputation: 2516

It sounds like you need to wrap your Output TextBox in a ScrollViewer and also assure it does stay in the bottom (defining some rows in the Grid or docking it to the bottom of a DockPanel.

EDIT: Do you need something like this?

<Grid x:Name="grd01">
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition Height="35" />
  </Grid.RowDefinitions>

  <ScrollViewer Grid.Row="1">
    <TextBox HorizontalAlignment="Stretch" TextWrapping="Wrap" />
  </ScrollViewer>
</Grid>

SECOND EDIT:

<Grid x:Name="grd01">
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition Height="35" />
  </Grid.RowDefinitions>

  <ScrollViewer Grid.Row="0">
    <StackPanel>
      <TextBox x:Name="input"
                HorizontalAlignment="Stretch"
                TextWrapping="Wrap" />
    </StackPanel>
  </ScrollViewer>

  <ScrollViewer Grid.Row="1">
    <TextBox x:Name="output"
              HorizontalAlignment="Stretch"
              TextWrapping="Wrap" />
  </ScrollViewer>
</Grid>

Upvotes: 1

cppanda
cppanda

Reputation: 1315

you can use this tweak on the window loaded event with this code: EDIT: i modified it so it's even correct if resizing now

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        output.MaxHeight = output.ActualHeight;
        output.VerticalAlignment = VerticalAlignment.Top;
        output.Height = output.MaxHeight;
    }

    private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        output.MaxHeight = output.MinHeight = output.Height = outGrid.ActualHeight;
    }

-

<ScrollViewer Height="Auto">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" >
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
            <TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" />
        </StackPanel>
        <Grid DockPanel.Dock="Bottom" Name="outGrid">
            <TextBox Name="output" TextWrapping="Wrap" AcceptsReturn="True" HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" VerticalAlignment="Stretch" />
        </Grid>
    </DockPanel>
</ScrollViewer>

Upvotes: 1

Related Questions