WPF DataGrid:是否可以按列而不是按像素水平滚动(也称为内容滚动)



在 WPF DataGrid 中,默认情况下内置了按行滚动的功能。 也就是说,单击 DataGrid 中垂直滚动条上的向下箭头,然后精确向下滚动一行。 但是,如果您单击水平滚动条上的右箭头,则不会向右移动一列 - 只需向右移动一些固定数量的像素。 我想单击右箭头并向右滚动一列。 同样,如果用户单击并拖动水平滚动条,我希望滚动仅按列增量滚动,而不是按像素增量滚动。

是否可以设置 WPF 数据网格,以便按列而不是按像素完成水平滚动?

编辑:我还希望用户能够通过单击和拖动拇指来水平滚动,类似于垂直滚动按行工作的方式。

一种解决方案是处理 ScrollViewer.ScrollChanged 事件...

<DataGrid x:Name="myGrid" ScrollViewer.ScrollChanged="dg_ScrollChanged"/>

并以编程方式滚动到下一列偏移量,如下所示:

    private void dg_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.HorizontalChange != 0) // horizontal scroll
        {
            if (e.OriginalSource is ScrollViewer)
            {
                // scoll to column offset
                ScrollViewer sv = e.OriginalSource as ScrollViewer;
                sv.ScrollToHorizontalOffset(GetColumnOffset(e.HorizontalChange > 0, sv.HorizontalOffset - e.HorizontalChange, sv.ScrollableWidth));
                e.Handled = true;
            }
        }
    }

您必须编写"GetColumnOffset"方法。这是我拼凑的一个快速而肮脏的实现。你可能会让它更干净,我没有进行彻底的测试,所以它可能包含错误:

    private double GetColumnOffset(bool forward, double currentPos, double maxOffset)
    {
        ObservableCollection<DataGridColumn> Columns = myGrid.Columns;
        double columnPosition = 0;
        double maxColumnPosition = 0;
        double maxColumnIndex = 0;
        foreach (var column in Columns)
        {
            columnPosition += column.ActualWidth;
            if (columnPosition < maxOffset)
            {
                maxColumnPosition = columnPosition;
                maxColumnIndex = Columns.IndexOf(column);
            }
            if (forward && columnPosition > currentPos)
            {
                return columnPosition;
            }
        }
        if (!forward)
        {
            columnPosition = maxColumnPosition;
            if (maxColumnPosition < currentPos)
            {
                return maxColumnPosition;
            }
            foreach (var column in Columns.Reverse())
            {
                if (Columns.IndexOf(column) <= maxColumnIndex)
                {
                    columnPosition -= column.ActualWidth;
                    if (columnPosition < currentPos)
                    {
                        return columnPosition;
                    }
                }
            }
        }
        return 0;
    }

最新更新