我有一个
DataGrid
,里面有一个 ScrollViewer
RowDetailTemplate
。我已经实现了 PreviewMouseWheel
事件的处理程序,并且如果 DataGrid
尚未到达它的 ScrollViewer
或者位于它的 ScrollableHeight
边缘,我会将滚动转发到 ScrollableHeight
。
这是可行的,但是当
RowDetails
占据了 DataGrid
的大部分视图时,在当前项目的垂直偏移下方滚动只会跳到下一个而不是平滑滚动。
据我了解,如果 ScrollViewer
´s VerticalOffset
属性是 ScrollViewer
(这里就是这种情况),则 CanContentScroll
´s true
位于项目而不是 DPI 中。我尝试过滚动 0.5 而不是 1,但这不起作用。
有办法解决这个问题吗?例如,通过强制偏移进入 DPI 模式或类似的方式?
这是我的数据网格:
<DataGrid x:Name="dgV" ItemsSource="{Binding Path=DataContext}" PreviewMouseLeftButtonUp="dgV_PreviewMouseLeftButtonUp" CanUserSortColumns="True" CanUserReorderColumns="True" CanUserResizeColumns="True" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False"
HeadersVisibility="Column" AlternationCount="2" >
<DataGrid.Resources>
<!-- cut for brevity -->
</DataGrid.Resources>
<DataGrid.Columns>
<!-- cut for brevity -->
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<ScrollViewer HorizontalContentAlignment="Stretch" MaxHeight="300" PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UIElement}}" CanContentScroll="True">
<!-- cut for brevity -->
</ScrollViewer>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
这是我的处理程序:
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if(sender is ScrollViewer scrollViewer && !e.Handled)
{
if(scrollViewer.ActualHeight < scrollViewer.MaxHeight || (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight && e.Delta < 0) || (scrollViewer.VerticalOffset == 0 && e.Delta > 0))
{
e.Handled=true;
var scv = ScrollViewerHelper.GetScrollViewer(dgV);
if (scv != null)
{
var d = e.Delta / 120;
//delta is always 120 which leads to a huge jump, apparently if cancontentscroll = true offset is in items rather than dpi
scv.ScrollToVerticalOffset(scv.VerticalOffset - d);
}
}
}
}
以下是一些截图来演示该问题:
起始状态:
向下滚动:
我想要的结果:
我找到了一种解决方法,可以在一定程度上解决我的问题。它仍然没有解决滚动不稳定的问题,但至少解决了
DetailRow
内容的跳转问题。
不过,如果有人对最初的问题有答案,请发表评论。
解决方法是根据
MaxHeight
的 ScrollViewer
限制 ActualHeight
的 DataGrid
,以便始终至少有 2 个 DataGridRow
可见。
ScrollViewer
:
<ScrollViewer HorizontalContentAlignment="Stretch" MaxHeight="{Binding Path=ActualHeight, Converter={StaticResource rowDetailsHeightConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" ..>
转换器实现:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//DataGridRowHeight / Header height = 25
double targetHeight = (double)value - 100;
return targetHeight > 30 ? targetHeight : 30;
}