WPF ScrollViewer 将控件推出 window

WPF ScrollViewer pushing control out of window

我有一个 DockPanel,其中包含一些控件,包括 ScrollViewer

我想要的是 ScrollViewer 允许滚动网格,而不会将其他控件推离表单底部。

相反,ScrollViewer 扩展到 window 的高度,而不是 Button 的顶部,将 Button 推到 Button 的底部形式。为什么是这样?我该如何解决?

<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>

我想要屏幕顶部的菜单栏,屏幕底部的按钮,以及中间带有 ScrollViewer 的网格。我做错了什么?

问题是 ScrollViewer 不知道它应该达到多少高度。 ScrollViewer 是一个控件,它试图获得其子项所需的大小。 DockPanel 还提供了 ScrollViewer 需要的大小,因此也是您的问题。您可以用像素固定 ScrollViewer 的高度(即 Height=100),使其成为固定高度。我不知道您的用例,所以如果您要显示图像轮播,这可能会有用。

在更一般的布局建议中,我可能会说您最好使用网格而不是 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>

我发现如果我将整个东西都放在网格中,我可以使用 DockPanel 获得动态高度。这似乎有效,因为我现在可以为 ScrollViewer.

设置动态高度
<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">
  <Grid>
      <Grid.ColumnDefinitions>
          <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
          <RowDefinition Height="*" />
          <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>
      <DockPanel Grid.Column="0" Grid.Row="0" LastChildFill="False">

除了我将按钮移出 DockPanel 并移到网格的第二行外,一切都正常了:

        </DockPanel>
    <Button Grid.Column="0" Grid.Row="1" Name="btnButton1" DockPanel.Dock="Bottom" Click="btnButton1_Click" >ButtonText</Button>
</Grid>

Height 为 "Auto" 的行将调整大小以适合其内容。带有星号 (*) 的 Height 行的大小将在计算汽车的大小后填充剩余的 space。因此一切都正确而漂亮地调整大小。

或者,此时我可以完全取消 DockPanel,并拥有 MenuToolBarTrayScrollViewerButton在他们自己单独的网格行中,就像 Emad 在他们的答案中建议的那样(尽管我不确定在他们的示例中额外的行是什么)。

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

我最终决定采用这种方法,所以我将其标记为答案,但我将所有内容放在这里是为了完整的解释和完整性(以防人们碰巧想要保留他们的DockPanel).