您可以欺骗数据网格将其 ScrollViewer 公开为每个网格的公共属性,例如在用户控件初始化期间调用 innerGridControl_ScrollChanged() 处理程序时。要公开它,您可以在 xaml 视图文件中创建网格,然后在另一个 xaml 视图中组合其中的两个。下面的代码在 innerGrid.xaml.cs 上,例如:
public ScrollViewer Scroller { get; set; } // exposed ScrollViewer from the grid
private bool _isFirstTimeLoaded = true;
private void innerGridControl_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (_isFirstTimeLoaded) // just to save the code from casting and assignment after 1st time loaded
{
var scroller = (e.OriginalSource) as ScrollViewer;
Scroller = scroller;
_isFirstTimeLoaded = false;
}
}
在 OuterGridView.xaml 上放置一个附加的事件处理程序定义:
<Views:innerGridView Grid.Row="1" Margin="2,0,2,2" DataContext="{Binding someCollection}"
x:Name="grid1Control"
ScrollViewer.ScrollChanged="Grid1Attached_ScrollChanged"
></Views:innerGridView>
<Views:innerGridView Grid.Row="3" Margin="2,0,2,2" DataContext="{Binding someCollection}"
x:Name="grid2Control"
ScrollViewer.ScrollChanged="Grid2Attached_ScrollChanged"
></Views:innerGridView>
然后在发生另一个滚动事件时访问该公共 ScrollViewer.SetHorizontalOffset(e.HorizontalOffset) 方法。下面的代码位于处理程序定义之一的 OuterGridView.xaml.cs 中(
private void Grid1Attached_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e != null && !e.Handled)
{
if (e.HorizontalChange != 0.0)
{
grid2Control.Scroller.ScrollToHorizontalOffset(e.HorizontalOffset);
}
e.Handled = true;
}
}
private void Grid2Attached_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e != null && !e.Handled)
{
if (e.HorizontalChange != 0.0)
{
grid1Control.Scroller.ScrollToHorizontalOffset(e.HorizontalOffset);
}
e.Handled = true;
}
}
还要确保内部网格内的任何其他 scroll_changed 事件(如果有,例如,如果您在其中一个列数据模板中定义具有默认滚动条的 TextBox)将其 e.Handled 设置为 true 以防止外部网格的处理程序处理它(此由于 routedevents 的默认冒泡行为而发生)。或者,您可以添加额外的 if 检查 e.OriginalSource 或 e.Source 以过滤您打算处理的滚动事件。