WPF Datagrid 行拉伸以填充 space,没有滚动条

WPF Datagrid rows stretch to fill space with no scrollbars

每当 Window 处于任何大小时,我都无法让我的 DataGrid 拉伸行以填充所有可用的 space。在这种情况下,它应该填充父网格第二行 (7*) 中的所有 space。 DataGrid 将始终有 20 行和 2 列。我不想显示任何滚动条。

我希望 DataGrid 看起来像这样:

但是,如果 Window 太短,项目将被截断:

如果Window太高,datagrid底部有一个难看的灰色区域:

这是Xaml:

<UserControl
    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:ignore="http://www.galasoft.ch/ignore"
    xmlns:viewModel="clr-namespace:WMT.ViewModel"
    xmlns:view="clr-namespace:WMT.View"
    xmlns:Design="clr-namespace:WMT.Design"
    xmlns:res="clr-namespace:WMT.Resources"
    xmlns:local="clr-namespace:WMT"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:Custom="http://www.galasoft.ch/mvvmlight"
    xmlns:debug="debug-mode"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    xmlns:Converters="clr-namespace:GTP.Contracts.Converters;assembly=GTP.Contracts"
    xmlns:Behaviours="clr-namespace:GTP.Contracts.Behaviours;assembly=GTP.Contracts"
    x:Class="WMT.View.FRView"
    mc:Ignorable="d mc"
    d:DesignWidth="706"
    d:DesignHeight="554" 
    d:DataContext="{d:DesignInstance {x:Type Design:DesignFRViewModel}, IsDesignTimeCreatable=True}" ScrollViewer.VerticalScrollBarVisibility="Disabled"
    >
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/WMT;component/Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Converters:NegateConverter x:Key="NegateConverter"/>
        <System:Double x:Key="StandardWidth">240</System:Double>
        <Thickness x:Key="StandardMargin">0,0,10,0</Thickness>
    </ResourceDictionary>
</UserControl.Resources>
<UserControl.Background>
    <ImageBrush ImageSource="/WMT;component/Images/cloud.bmp"/>
</UserControl.Background>

<Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.5*"/>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="2.5*"/>
    </Grid.RowDefinitions>
    <DataGrid Grid.Row="1" 
              ItemsSource="{Binding WmtResult.Responses}" 
              AutoGenerateColumns="False" 
              CanUserReorderColumns="False" 
              CanUserResizeColumns="False" 
              CanUserSortColumns="False" 
              GridLinesVisibility="None" 
              CanUserAddRows="False" 
              CanUserDeleteRows="False" 
              CanUserResizeRows="False" 
              RowHeaderWidth="0" 
              HorizontalContentAlignment="Stretch" 
              VerticalContentAlignment="Stretch" 
              HorizontalScrollBarVisibility="Disabled" 
              VerticalScrollBarVisibility="Disabled">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding IRPrompt.Item}" 
                                ClipboardContentBinding="{x:Null}"
                                Width="3*" 
                                Header="Word"/>
            <DataGridTextColumn Binding="{Binding FRPrompt}" 
                                ClipboardContentBinding="{x:Null}" 
                                Width="*" 
                                Header="Count"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

我试过使用 ListView 而不是 DataGrid,但遇到了类似的问题。我需要在某处使用 Viewbox 吗?如果您需要更多信息,请告诉我。谢谢。

编辑

我正在尝试 Ryan Flohr 提出的将 DataGrid 放在 Viewbox 中的建议。这解决了截断问题和 DataGrid 问题下方的灰色区域。 DataGrid 正确地垂直填充了 space,但是它没有水平填充 space。

这是更新后的 xaml:

<UserControl
    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:ignore="http://www.galasoft.ch/ignore"
    xmlns:viewModel="clr-namespace:WMT.ViewModel"
    xmlns:view="clr-namespace:WMT.View"
    xmlns:Design="clr-namespace:WMT.Design"
    xmlns:res="clr-namespace:WMT.Resources"
    xmlns:local="clr-namespace:WMT"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:Custom="http://www.galasoft.ch/mvvmlight"
    xmlns:debug="debug-mode"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    xmlns:Converters="clr-namespace:GTP.Contracts.Converters;assembly=GTP.Contracts"
    xmlns:Behaviours="clr-namespace:GTP.Contracts.Behaviours;assembly=GTP.Contracts"
    x:Class="WMT.View.FRView"
    mc:Ignorable="d mc"
    d:DesignWidth="754"
    d:DesignHeight="685" 
    d:DataContext="{d:DesignInstance {x:Type Design:DesignFRViewModel}, IsDesignTimeCreatable=True}" ScrollViewer.VerticalScrollBarVisibility="Disabled"
    >
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/WMT;component/Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Converters:NegateConverter x:Key="NegateConverter"/>
        <System:Double x:Key="StandardWidth">240</System:Double>
        <Thickness x:Key="StandardMargin">0,0,10,0</Thickness>
    </ResourceDictionary>
</UserControl.Resources>
<UserControl.Background>
    <ImageBrush ImageSource="/WMT;component/Images/cloud.bmp"/>
</UserControl.Background>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.5*"/>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="2.5*"/>
    </Grid.RowDefinitions>
    <Viewbox Grid.Row="1">
        <DataGrid Grid.Row="1" 
                  ItemsSource="{Binding WmtResult.Responses}" 
                  AutoGenerateColumns="False" 
                  CanUserReorderColumns="False" 
                  CanUserResizeColumns="False" 
                  CanUserSortColumns="False" 
                  GridLinesVisibility="None" 
                  CanUserAddRows="False" 
                  CanUserDeleteRows="False" 
                  CanUserResizeRows="False" 
                  RowHeaderWidth="0" 
                  VerticalContentAlignment="Stretch" 
                  HorizontalScrollBarVisibility="Disabled" 
                  VerticalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding IRPrompt.Item}" 
                                    ClipboardContentBinding="{x:Null}" 
                                    Header="Word"
                                    >
                    <!--<DataGridTextColumn.CellStyle>
                        <Style TargetType="{x:Type DataGridCell}">
                            <Setter Property="Margin" Value="0,0,190,0" />
                        </Style>
                    </DataGridTextColumn.CellStyle>-->
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding FRPrompt}" 
                                    ClipboardContentBinding="{x:Null}" 
                                    Header="Count">
                    <!--<DataGridTextColumn.CellStyle>
                        <Style TargetType="{x:Type DataGridCell}">
                            <Setter Property="Margin" Value="0,0,60,0" />
                        </Style>
                    </DataGridTextColumn.CellStyle>-->
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Viewbox>

</Grid>

截图如下:

我尝试使用 DataGrid 的 Horizo​​ntalAlignment 和 Horizo​​ntalContentAlignment,但没有成功。然后我更改了列的边距(参见 xaml 的注释部分),但只有当 Window 是一定大小时才能获得适当的边距。这是我将边距设置为精确值时的屏幕截图(请参阅 xaml 中注释的 CellStyle 部分):

我想我可以使用 ValueConverter 将边距绑定到 Viewbox 实际宽度的百分比,但这看起来很老套。

有没有办法用某种布局控件替换 DataGrid 的内部 StackPanel,以水平填充 space?第一列的宽度应为第二列的 3 倍。

如果您希望显示所有二十行,即使 window 尺寸太小,同时不显示任何垂直滚动条,您也必须将 DataGrid 放在 ViewBox 中。这也将确保 "ugly gray" 不会显示。

在 DataGrid 控件内部,内容本身位于 StackPanel 内部,它会增长到 space 内容本身需要的任何大小。 StackPanel 位于 ScrollViewer 内部,因此如果内容对于 Window 来说太大了,您可以滚动它。由于您禁用了滚动条功能,它实际上只是一个将继续增长的 StackPanel。由于您已经在 Grid 上设置了明确的大小限制,因此 DataGrid 将只显示其大小允许的 DataGrid 部分,从而使内容看起来被截断了。另一方面,如果网格增长得比 StackPanel 中的内部内容大得多,则 StackPanel 的大小会适应网格,但其内容会在它停止的地方停止。您看到的 "ugly" 灰色是控件的背景颜色。

我能够通过在 DataGrid 周围使用 Viewbox 并将 Stretch 设置为 Fill 来获得所需的结果。我还必须在 DataGrid 上设置一个高度和一个宽度,以便在更改 Window 大小时为其提供一个纵横比。这是 xaml:

<UserControl
    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:ignore="http://www.galasoft.ch/ignore"
    xmlns:viewModel="clr-namespace:WMT.ViewModel"
    xmlns:view="clr-namespace:WMT.View"
    xmlns:Design="clr-namespace:WMT.Design"
    xmlns:res="clr-namespace:WMT.Resources"
    xmlns:local="clr-namespace:WMT"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:Custom="http://www.galasoft.ch/mvvmlight"
    xmlns:debug="debug-mode"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    xmlns:Converters="clr-namespace:GTP.Contracts.Converters;assembly=GTP.Contracts"
    xmlns:Behaviours="clr-namespace:GTP.Contracts.Behaviours;assembly=GTP.Contracts"
    x:Class="WMT.View.FRView"
    mc:Ignorable="d mc"
    d:DesignWidth="688"
    d:DesignHeight="554" 
    d:DataContext="{d:DesignInstance {x:Type Design:DesignFRViewModel}, IsDesignTimeCreatable=True}" ScrollViewer.VerticalScrollBarVisibility="Disabled"
    >
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/WMT;component/Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Converters:NegateConverter x:Key="NegateConverter"/>
        <System:Double x:Key="StandardWidth">240</System:Double>
        <Thickness x:Key="StandardMargin">0,0,10,0</Thickness>
    </ResourceDictionary>
</UserControl.Resources>
<UserControl.Background>
    <ImageBrush ImageSource="/WMT;component/Images/cloud.bmp"/>
</UserControl.Background>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.5*"/>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="2.5*"/>
    </Grid.RowDefinitions>
    <Viewbox Grid.Row="1" Stretch="Fill">
        <DataGrid Grid.Row="1"
                  Background="White"
                  ItemsSource="{Binding WmtResult.Responses}" 
                  AutoGenerateColumns="False" 
                  CanUserReorderColumns="False" 
                  CanUserResizeColumns="False" 
                  CanUserSortColumns="False" 
                  GridLinesVisibility="None" 
                  CanUserAddRows="False" 
                  CanUserDeleteRows="False" 
                  CanUserResizeRows="False" 
                  RowHeaderWidth="0" 
                  VerticalContentAlignment="Stretch" 
                  HorizontalScrollBarVisibility="Disabled" 
                  VerticalScrollBarVisibility="Disabled"
                  HorizontalContentAlignment="Stretch"
                  ColumnWidth="*"
                  IsReadOnly="True"
                  Height="385" Width="300">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding IRPrompt.Item}" 
                                    ClipboardContentBinding="{x:Null}" 
                                    Header="Word"
                                    Width="2*"
                                    >
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding FRPrompt}" 
                                    ClipboardContentBinding="{x:Null}" 
                                    Header="Count"
                                    Width="*">
                  </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Viewbox>

</Grid>