WPF数据表格的水平滚动条没有显示

21

我创建了一个简单的DataGrid,其中有4列超出了DataGrid的边界,水平滚动条没有显示。我尝试为每一列设置宽度,但仍然没有改变。这是我的XAML代码:

<Window x:Class="WPFTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <DataGrid Height="200" Width="200" HorizontalScrollBarVisibility="Visible">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Column 1" />
                <DataGridTextColumn Header="Column 2" />
                <DataGridTextColumn Header="Column 3" />
                <DataGridTextColumn Header="Column 4" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

以下是我的结果:

在此输入图像描述

我也尝试将DataGrid与ScrollViewer一起包装,但没有效果。如何让滚动条出现?


你尝试过将 CanContentScroll 设置为 true 吗?此外,我认为当 Datagrid 为空时,ScrollViewer 不会处理任何内容。你可以尝试填充列并查看是否出现滚动条? - Damascus
是的,一旦您在DataGrid中有内容,滚动条就会出现,这是DataGrid的默认行为。我不确定如何覆盖它,即如何在没有数据的情况下显示滚动条。 - Haris Hasan
@Damascus 你说得对。当我设置了ItemsSource后,滚动就可以工作了。谢谢。请把你的评论发布为答案,这样我就可以接受它了。 - Vale
11个回答

22

我也非常不喜欢这种行为,因为我使用标题过滤器。我的“hack”比上面的方法要简单得多:只需将数据网格放置在一个新的带有HorizontalScrollBarVisibility=AutoVerticalScrollBarVisibility=Disabled属性的ScrollViewer中(数据网格已经可以很好地处理它)。就像这样:

<ScrollViewer HorizontalScrollBarVisibility="Auto"
              VerticalScrollBarVisibility="Disabled">
    <DataGrid>
        ...
    </DataGrid>
</ScrollViewer>

确实,页面上会有更多的控件,但比上面那段hacky代码容易得多。到目前为止,我还没有找到一种让数据网格自动执行此操作的方法。

该解决方案的副作用可能是垂直滚动条隐藏,直到您向右滚动。


9
注意:如果您希望列调整大小时出现水平滚动条,请勿在数据网格列宽度中使用“*”。 - Ranu Mandan
3
使用这个解决方案时,即使列表中有项目,它仍然会使用外部的水平滚动条。这意味着垂直滚动条将滚动到视图之外,这并不是很可行。 - raznagul
如果鼠标滚轮无法进行垂直滚动,请参考此链接 - Yusuf Tarık Günaydın
行标题将超出可见区域。 - thetaprime
@lauren 我已经尝试了您在这里提到的内容,那么水平滚动条出现得很完美,但是正如您所提到的,垂直滚动条直到移动到左侧才会出现。您能否给出一些建议? - siyumi_amarasinghe

4
这对我来说是个重大问题,因为我正在创建许多列,并允许用户通过在标题中放置筛选控件进行筛选。当用户向右滚动并在一列中放置筛选器时,如果由于这些条件未返回任何行,则整个网格将向左移动(所有列移到默认左侧位置),水平滚动条将消失,因此用户无法滚动到筛选列以撤销操作!这是一个很大的痛点!我刚刚在代码中放置的“hack”是解决它的方法:(_dv指向来自DataTable的DataView)
// construct an overall sql filter statement
string sqlFilter = _setttings.SGColumns.GetFilterSQL();

BindingListCollectionView view = CollectionViewSource.GetDefaultView(gridMain.ItemsSource) as BindingListCollectionView;

if (view != null)
    view.CustomFilter = sqlFilter;      // "XGROUP = 'E' AND GEOG = 'U'";

if (view != null && _dv.Count == 0)
{
    gridMain.ItemsSource = null;
    gridMain.Items.Add("hello");
    _RowHeightTemp = gridMain.RowHeight;
    gridMain.RowHeight = 0;
}
else
{
    if (gridMain.Items.Count == 1 && gridMain.Items[0].ToString() == "hello")
    {
        gridMain.Items.Clear();
        gridMain.ItemsSource = _dv;
        view = CollectionViewSource.GetDefaultView(gridMain.ItemsSource) as BindingListCollectionView;
        view.CustomFilter = sqlFilter;
        gridMain.RowHeight = _RowHeightTemp;
    }
}

现在,当没有行显示时,这确保了网格保持在其精确位置!


3

我认为当Datagrid为空时,ScrollViewer不会处理任何内容。尝试通过添加ItemsSource来填充列,因此滚动应该会出现 :)


2

只要向网格添加一些数据,滚动条就会自动工作。你可以尝试使用以下代码进行测试:

将你的网格命名为 "grid"

附加窗口加载事件

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        grid.Items.Add(new object());
    }

你会看到滚动条出现。

1

虽然这个问题很旧,但我认为它可能会帮助到某些人。基于Lauren的答案:

<ScrollViewer VerticalScrollBarVisibility="Disabled">
    <DataGrid x:Name="ScrollDataGrid"
        HorizontalScrollBarVisibility="Auto"
        VerticalScrollBarVisibility="Auto" ... >
    </DataGrid>
    <ScrollViewer.Style>
        <Style BasedOn="{StaticResource {x:Type ScrollViewer}}" TargetType="ScrollViewer">
            <Setter Property="HorizontalScrollBarVisibility" Value="Disabled" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=ScrollDataGrid, Path=Items.Count}" Value="0">
                    <Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ScrollViewer.Style>
</ScrollViewer>

如果DataGrid有记录,则ScrollViewer不会显示滚动条,并使用DataGrid的滚动条。

0

显然你需要水平滚动条。

需要做两件事:

1. 在你的DataGrid中添加属性IsReadOnly="True"

2. 在你的ScrollViewer中添加MaxWidth="1200" VerticalScrollBarVisibility="Auto"

需要设置MaxWidth,你可以根据需要将1200更改为任何其他值。

<ScrollViewer MaxWidth="1200" VerticalScrollBarVisibility="Auto">
    <DataGrid IsReadOnly="True">

    </DataGrid>
</ScrollViewer>

0

参考Marcel的回答,我制作了这个版本

窗口资源:

<CollectionViewSource x:Key="NormalCollectionView" Source="{Binding Items}" Filter="CollectionViewSource_Filter"/>
<CollectionViewSource x:Key="EmptyCollectionView"/>

数据网格样式:

<DataGrid.Style>
  <Style TargetType="DataGrid">
    <Style.Triggers>
      <DataTrigger Binding="{Binding IsEmpty, Source={StaticResource NormalCollectionView}}" Value="True">
        <Setter Property="ItemsSource" Value="{Binding Source={StaticResource EmptyCollectionView}}"/>
        <Setter Property="RowHeight" Value="0"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding IsEmpty, Source={StaticResource NormalCollectionView}}" Value="False">
        <Setter Property="ItemsSource" Value="{Binding Source={StaticResource NormalCollectionView}}"/>
      </DataTrigger>
    </Style.Triggers>
  </Style>
</DataGrid.Style>

public MyWindow()
{
  InitializeComponent();
  var emptyCollectionView = Resources["EmptyCollectionView"] as CollectionViewSource;
  emptyCollectionView.Source = new ObservableCollection<MyDataType>
  {
    new MyDataType()
  };
  emptyCollectionView.View.Refresh();
}

private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
  var datacontext = DataContext as MyDataContextType;
  e.Accepted = datacontext.CheckFilterForLine(e.Item as MyDataType);
}
  • emptyCollectionView.View.Refresh(); 可能不是必要的
  • 在xaml中初始化“空”集合可能有更好的方法。

我之所以这样做,是因为我有一些冻结列,我认为用ScrollViewer包装它们不起作用。我喜欢Marcel的答案,但不想处理手动网格项管理,并且在某些时候,由于所有事件而变得混乱。


0

仅当列宽之和超过可用宽度时,水平滚动条才会显示出来。最简单的方法是使用 Width="SizeToCells" 要求 WPF 根据其内容调整列的宽度。


0
Datagrid 的属性设置为 CanUserAddRows="True" IsReadOnly="True" 并用 ScrollViewer 包装它。 CanUserAddRows 会给你一个空行,这个空行会保留滚动条。 IsReadOnly 会隐藏这行因为它是只读的。

缺点是,当您垂直滚动 datagrid 时,标题栏会被隐藏。


0
在我的情况下,我有几列的宽度设置为“*”。这会导致弹性大小调整,这意味着在DataGrid上永远不需要水平滚动条。一旦我将宽度设置为“Auto”,水平滚动条就出现了。
默认宽度是“*”,因此必须明确更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接