C#WPF - 使DataGrid伸展到可用大小,而不是扩展可用大小

时间:2017-09-13 11:22:44

标签: c# wpf visual-studio-2010 datagrid width

我使用Visual Studio 2010.我一直在努力尝试获取数据网格来填充现有空间。如有必要,在数据网格上显示滚动条,而不是在页面上显示。

示例代码:

<Page x:Class="TestApp.Page1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  mc:Ignorable="d" 
  d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition Height="200"/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>
    <Expander x:Name="MyExpander"
              Grid.Column="1"
              Grid.Row="1"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Top"
              Header="My Expander"
              Expanded="MyExpander_Expanded"
              Collapsed="MyExpander_Collapsed">
        <Viewbox Stretch="Uniform">
        <StackPanel>
            <DataGrid Margin="5"
                      Height="100"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      HorizontalScrollBarVisibility="Auto"
                      VerticalScrollBarVisibility="Auto">
            <DataGrid.Columns>
                <DataGridTextColumn Header="MyFirstColumn"/>
                <DataGridTextColumn Header="MySecondColumn"/>
                <DataGridTextColumn Header="MyThirdColumn"/>
                <DataGridTextColumn Header="MyFourthColumn"/>
                <DataGridTextColumn Header="MyFifthColumn"/>
                <DataGridTextColumn Header="MySixthColumn"/>
                <DataGridTextColumn Header="MySeventhColumn"/>
                <DataGridTextColumn Header="MyEighthColumn"/>
                <DataGridTextColumn Header="MyNinthColumn"/>
                <DataGridTextColumn Header="MyTenthColumn"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="DoSomething"
                Margin="5"
                Width="100"
                Height="30"
                Content="Do Something"
                Click="DoSomething_Click"/>
        </StackPanel>
        </Viewbox>
    </Expander>
</Grid>

问题是,无论我做什么,数据网格总是会拉伸,直到所有列都完全可见,即使它延伸超过窗口(或页面)大小。 注意:我右边有一个面板,显示状态,日期,信息......,它们应保留在屏幕上。

我已经尝试了很多东西来列出它们。我找到的唯一可行的“解决方案”是在网格上添加另一个控件(不可见),就像分隔符一样,并将扩展器宽度绑定到分隔符的宽度。它有效,但这是糟糕的编程。

MaxWidth="{Binding ElementName=MySeparator, Path=ActualWidth}"

将stackpanel的宽度绑定到列的(实际)宽度只会使stackpanel消失。

有人可以帮助我。谢谢。

- 更新 - 这就是我想要实现的目标: enter image description here

似乎如果我使用硬编码列宽,则不会发生此问题。只有存在具有星形长度的列时,数据网格才会占用所需的空间。

4 个答案:

答案 0 :(得分:1)

由于您的图表仅解决了滚动问题,因此我现在专注于此。我还不完全清楚你需要在滚动之前想要这个布局看起来,但是让我们以此为出发点。尝试一下,如果行为不是你的想法,请尽可能具体地说明需要改变什么(图片胜过千言万语)。

为简洁起见,我只包含Expander及其内容。祖先元素与原始帖子完全一样。

<Expander x:Name="MyExpander"
          Grid.Column="1"
          Grid.Row="1"
          VerticalAlignment="Top"
          Header="My Expander"
          Expanded="MyExpander_Expanded"
          Collapsed="MyExpander_Collapsed">
  <StackPanel>
    <DataGrid Margin="5"
              xmlns:s="clr-namespace:System;assembly=mscorlib">
      <!-- Temporary items source to demonstrate grid measuring to fit rows -->
      <DataGrid.ItemsSource>
        <x:Array Type="s:String">
          <s:String>Dummy Row 1</s:String>
          <s:String>Dummy Row 2</s:String>
          <s:String>Dummy Row 3</s:String>
        </x:Array>
      </DataGrid.ItemsSource>
      <DataGrid.Columns>
        <DataGridTextColumn Header="MyFirstColumn" />
        <DataGridTextColumn Header="MySecondColumn" />
        <DataGridTextColumn Header="MyThirdColumn" />
        <DataGridTextColumn Header="MyFourthColumn" />
        <DataGridTextColumn Header="MyFifthColumn" />
        <DataGridTextColumn Header="MySixthColumn" />
        <DataGridTextColumn Header="MySeventhColumn" />
        <DataGridTextColumn Header="MyEighthColumn" />
        <DataGridTextColumn Header="MyNinthColumn" />
        <DataGridTextColumn Header="MyTenthColumn" />
      </DataGrid.Columns>
    </DataGrid>
    <Button x:Name="DoSomething"
            Margin="5"
            Width="100"
            Height="30"
            Content="Do Something"
            Click="DoSomething_Click" />
  </StackPanel>
</Expander>

这是两列的看法:

[Grid with 2 Columns[2]

这是十列的看法:

Grid with 10 Columns

更新

根据您对其他答案的评论,您的页面在运行时加载到ScrollViewer内。如果ScrollViewer支持水平滚动,那么这就是问题的根源:它会为您的页面提供所需的水平空间,并且需要由DataGrid驱动。一个(hacky)解决方法是将DataGrid包装在自定义装饰器中,该装饰器在测量时伪造其所需宽度,然后填充排列时可用的任何水平空间。如果您想尝试一下,请使用上面的示例,但将DataGrid包装在装饰器中,如下所示:

<l:ZeroWidthDecorator xmlns:l="clr-namespace:TestApp">
  <DataGrid><!-- ... --></DataGrid>
</l:ZeroWidthDecorator>

装饰器的代码如下:

public class ZeroWidthDecorator : Border
{
    private Size _lastSize;
    private Size _idealSize;

    protected override void OnVisualChildrenChanged(DependencyObject added, DependencyObject removed)
    {
        base.OnVisualChildrenChanged(added, removed);
        _idealSize = new Size();
        _lastSize = new Size();
    }

    protected override Size MeasureOverride(Size constraint)
    {
        var child = this.Child;
        if (child == null)
            return new Size();
        if (child.IsMeasureValid)
            child.Measure(new Size(_lastSize.Width, Math.Max(_lastSize.Height, constraint.Height)));
        else
            child.Measure(new Size(0d, constraint.Height));
        _idealSize = child.DesiredSize;
        return new Size(0d, _idealSize.Height);
    }

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        var child = this.Child;
        if (child != null)
        {
            if (arrangeSize != _lastSize)
            {
                // Our parent will assume our measure is the same if the last
                // arrange bounds are still available, so force a reevaluation.
                this.InvalidateMeasure();
            }
            child.Arrange(new Rect(arrangeSize));
        }
        _lastSize = arrangeSize;
        return arrangeSize;
    }
}

我还没有对此进行过广泛的测试,但我尝试了几种不同的方案,似乎可以正常工作。 使用它需要您自担风险。

答案 1 :(得分:1)

感谢大家的努力。该解决方案由Mike Strobel在评论中提出。由于我无法将评论标记为,我将在此重复。

我有一个窗口,其中包含一个滚动查看器,所有页面都放在上面。我从窗口中删除了scrollviewer并将滚动条放在页面上。

<Page x:Class=...>
    <ScrollViewer HorizontalScrollBarVisibility="Disabled"
                  VerticalScrollBarVisibility="Visible">
        <Grid>

这实际上解决了这个问题!谢谢迈克!

(如果你也遇到这个问题,请同时给mike的评论竖起大拇指。)

答案 2 :(得分:0)

尝试将DataGridScrollViewer这样包裹起来:

<ScrollViewer VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Auto">
    <DataGrid>
        // SOME CONTENT
    </DataGrid>
</ScrollViewer>

此外,我根本不知道您是否需要ViewBox。尝试删除它,看看它是否符合您的需求。

答案 3 :(得分:0)

摆脱StackPanel

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition Height="200"/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>
    <Expander x:Name="MyExpander"
              Grid.Column="1"
              Grid.Row="1"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Top"
              Header="My Expander"
              Expanded="MyExpander_Expanded"
              Collapsed="MyExpander_Collapsed">
        <Viewbox Stretch="Uniform">
            <DataGrid Margin="5"
                      Height="100"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      HorizontalScrollBarVisibility="Auto"
                      VerticalScrollBarVisibility="Auto">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="MyFirstColumn"/>
                    <DataGridTextColumn Header="MySecondColumn"/>
                    <DataGridTextColumn Header="MyThirdColumn"/>
                    <DataGridTextColumn Header="MyFourthColumn"/>
                    <DataGridTextColumn Header="MyFifthColumn"/>
                    <DataGridTextColumn Header="MySixthColumn"/>
                    <DataGridTextColumn Header="MySeventhColumn"/>
                    <DataGridTextColumn Header="MyEighthColumn"/>
                    <DataGridTextColumn Header="MyNinthColumn"/>
                    <DataGridTextColumn Header="MyTenthColumn"/>
                </DataGrid.Columns>
            </DataGrid>
            <Button x:Name="DoSomething"
                Margin="5"
                Width="100"
                Height="30"
                Content="Do Something"
                Click="DoSomething_Click"/>
        </Viewbox>
    </Expander>
</Grid>
由于StackPanels衡量其子女的方式,

ScrollViewersStackPanel不能很好地协同工作:

XAML/WPF - ScrollViewer which has StackPanel inside is not scrolling

由于DataGrid的默认控件模板包含ScrollViewer,因此您无需添加自己的模板。