在 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;
}