WPF/MVVM: Sync scrolling of two datagrids in diffe

2019-03-19 10:15发布

I have two datagrids side by side bound to different data tables and each with their own view.

The datatables both have the same number of rows, and I want both grids to maintain the same scroll position.

I am having trouble finding a way to do this using MVVM... anyone have any ideas?

Thanks! -Steven

4条回答
太酷不给撩
2楼-- · 2019-03-19 10:36

Take a look at codeproject Scroll Synchronization

查看更多
女痞
3楼-- · 2019-03-19 10:39

The Scroll Synchronization project doesn't work for Datagrid because it doesn't expose ScrollToVerticalOffset

查看更多
Viruses.
4楼-- · 2019-03-19 10:41

I was able to overcome this issue via some reflection hacks:

<DataGrid Name="DataGrid1" ScrollViewer.ScrollChanged="DataGrid1_ScrollChanged" />
<DataGrid Name="DataGrid2" />

and the code itself is:

    private void DataGrid1_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.HorizontalChange != 0.0f)
        {
            ScrollViewer sv = null;
            Type t = DataGrid1.GetType();
            try
            {
                sv = t.InvokeMember("InternalScrollHost", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, DataGrid2, null) as ScrollViewer;
                sv.ScrollToHorizontalOffset(e.HorizontalOffset);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
查看更多
看我几分像从前
5楼-- · 2019-03-19 11:02

The best way I've used so far is to use the VisualTreeHelper class to find the correct ScrollViewer object (grid or no grid). I've used this in several projects.

Try this if any of you need it:

private static bool ScrollToOffset(DependencyObject n, double offset)
{
    bool terminate = false;
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(n); i++)
    {
        var child = VisualTreeHelper.GetChild(n, i);
        if (child is ScrollViewer)
        {
            (child as ScrollViewer).ScrollToVerticalOffset(offset);
            return true;
        }
    }
    if (!terminate)
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(n); i++)
            terminate = ScrollToOffset(VisualTreeHelper.GetChild(n, i), offset);
     return false;
}

Note: I typically use ListBox classes and would pass it directly to this function.

Happy programming :)

查看更多
登录 后发表回答