解决方案:动态向上查找外层的ScrollViewer
并抛出事件。
后端:
private void InnerScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var scrollViewer = sender as ScrollViewer;
if (scrollViewer == null)
return;
bool scrollAtTop = scrollViewer.VerticalOffset == 0;
bool scrollAtBottom = scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight;
if ((e.Delta > 0 && scrollAtTop) || (e.Delta < 0 && scrollAtBottom))
{
// 尝试向上查找父级ScrollViewer
var parentScrollViewer = GetParentScrollViewer(scrollViewer);
if (parentScrollViewer != null)
{
e.Handled = true;
// 把事件“转发”给父ScrollViewer
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = UIElement.MouseWheelEvent,
Source = sender
};
parentScrollViewer.RaiseEvent(eventArg);
}
}
else
{
// 内部ScrollViewer自己处理
e.Handled = false; // 让它滚动
}
}
/// <summary>
/// 向上查找最近的父ScrollViewer,排除自己
/// </summary>
private ScrollViewer GetParentScrollViewer(DependencyObject start)
{
var parent = VisualTreeHelper.GetParent(start);
while (parent != null)
{
if (parent is ScrollViewer sv)
return sv;
parent = VisualTreeHelper.GetParent(parent);
}
return null;
}
前端:(引用一下InnerScrollViewer_PreviewMouseWheel这个事件就行)
<ScrollViewer HorizontalScrollBarVisibility="Auto" PreviewMouseWheel="InnerScrollViewer_PreviewMouseWheel"/>