Q:

WPF ScrollViewer pushing control out of window

I have a DockPanel, which contains some controls including a ScrollViewer.
What I WANT to happen, is for the ScrollViewer to allow the grid to be scrolled, without pushing other controls off the bottom of the form.
Instead, the ScrollViewer expands to the height of the window, rather than the top of the Button, pushing the Button off for the bottom of the form.  Why is this?  How do I fix it?
<Window x:Class="Class1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Class1"
    mc:Ignorable="d"
    Title="MainWindow" Height="800" Width="600"
    WindowStartupLocation="CenterScreen">
<DockPanel LastChildFill="False">
    <Menu DockPanel.Dock="Top">
        <MenuItem Header="File">
            <MenuItem Name="miQuit" Header="Quit" Click="miQuit_Click" />
        </MenuItem>
    </Menu>
    <ToolBarTray DockPanel.Dock="Top" IsLocked="True">
        <ToolBar>
            <Button Name="btnQuit" ToolBar.OverflowMode="Never" Click="btnQuit_Click">
                Quit
            </Button>
        </ToolBar>
    </ToolBarTray>
    <ScrollViewer VerticalScrollBarVisibility="Auto" DockPanel.Dock="Top" VerticalAlignment="Stretch">
        <Grid Name="gMainGrid" ScrollViewer.CanContentScroll="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBox Grid.Column="0" Grid.Row="0"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="1"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="2"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="3"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="4"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="5"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="6"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="7"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="8"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="9"   Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="10"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="11"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="12"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="13"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="14"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="15"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="16"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="17"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="18"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="19"  Width="100" Margin="10,10,10,10"/>
            <TextBox Grid.Column="0" Grid.Row="20"  Width="100" Margin="10,10,10,10"/>
        </Grid>
    </ScrollViewer>
    <Button Name="btnButton1" DockPanel.Dock="Bottom" Click="btnButton1_Click" >ButtonText</Button>
</DockPanel>

I want the menu bar at the top of the screen, the button at the bottom of the screen, and the grid with the ScrollViewer in the middle.  What am I doing wrong?

A:

The problem is that the ScrollViewer doesn't know how much height it should get. ScrollViewer is a control that tries to get as much size as its children need. DockPanel also gives as much size as the ScrollViewer need and therefore your problem. You can fix height of the ScrollViewer with pixels (i.e. Height=100) To make it a fixed height. I don't know your use case so this might be useful if you are showing an image carousel for example.
In more general layout advice I might say that you'd better use a grid instead of a DockPanel:
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
        <!-- Next one is for middle part of the page -->
        <RowDefinition Height="*" />
        <RowDefinition Height="auto" />
    </Grid.RowDefinitions>
    <!-- your controls here -->
</Grid>

