您可以通过在用户控件初始化期间调用innerGridControl_ScrollChanged()处理程序来欺骗datagrid,以公开每个网格的ScrollViewer属性。
要公开它,您可以在xaml View文件中创建网格,然后在另一个xaml View中组成两个网格。
以下代码示例在innerGrid.xaml.cs中:
public ScrollViewer Scroller { get; set; }
private bool _isFirstTimeLoaded = true;
private void innerGridControl_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (_isFirstTimeLoaded)
{
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,以防止外部网格处理它(这是由于路由事件的默认冒泡行为导致的)。或者,您可以在e.OriginalSource或e.Source上添加额外的if检查来过滤您打算处理的滚动事件。