代码之家  ›  专栏  ›  技术社区  ›  Philipp Schmid

同步2个WPF数据网格的滚动位置

  •  6
  • Philipp Schmid  · 技术社区  · 17 年前

    我正在努力 使同步 水平面 滚动位置 共2人 WPF数据网格 控制。

    卷轴变了 第一个DataGrid的事件:

    <toolkit:DataGrid x:Name="SourceGrid" ScrollViewer.ScrollChanged="SourceGrid_ScrollChanged">
    

    <toolkit:DataGrid x:Name="TargetGrid">
    

    在事件处理程序中,我试图使用 IScrollInfo.SetHorizontalOffset ,但遗憾的是,DataGrid没有公开 IScrollInfo :

    private void SourceGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ((IScrollInfo)TargetGrid).SetHorizontalOffset(e.HorizontalOffset);
        // cast to IScrollInfo fails
    }
    

    IScrollInfo

    顺便说一句,我是 使用冻结柱 ,因此我无法使用ScrollViewer包装这两个DataGrid控件。

    5 回复  |  直到 16 年前
        1
  •  3
  •   greenoldman    15 年前

    有一段很好的代码可以做到这一点:

    http://www.codeproject.com/KB/WPF/ScrollSynchronization.aspx

        2
  •  3
  •   Markus Jarderot    14 年前

    根据Microsoft产品组的说法,遍历可视树以查找ScrollViewer是推荐的方法,如下所示 explained in their answer on Codeplex .

        3
  •  1
  •   Tim Cooper    15 年前

    我们在使用基础设施网格时遇到了同样的问题,因为它 (仍然不支持)冻结列。所以我们有两个并排的网格,看起来像一个网格。左侧的网格没有水平滚动,但右侧的网格有。可怜人的冻柱。

    不管怎么说,我们最终只是把手伸进了视觉树,拉出了 ScrollViewer

    有兴趣听到你为什么需要这样做。

        4
  •  1
  •   JJ_Coder4Hire    13 年前

    这是一个很好的解决方案。我在WPF工作得很好。

    http://www.codeproject.com/Articles/39244/Scroll-Synchronization

    我刚刚引用了ScrollSynchronizer dll,添加了一个xml导入:

    然后把它添加到我的datagrids和你叔叔的bobs中:

    <DataGrid.Resources>
       <Style TargetType="ScrollViewer">
         <Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" />
       </Style>
    </DataGrid.Resources>
    
        5
  •  1
  •   mithocondria    12 年前

    例如,在初始化usercontrol期间调用innerGridControl_ScrollChanged()处理程序时,可以欺骗datagrid将其ScrollViewer作为每个网格的公共属性公开。 例如,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(即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事件(如果有,例如,如果在一个列数据模板中定义了一个带有默认scroller的文本框)的e.Handled设置为true,以防止外部网格的处理程序处理它(这是由于routedevents的默认冒泡行为造成的)。或者,您可以在e.OriginalSource或e.Source上添加额外的if检查,以过滤您打算处理的滚动事件。

    推荐文章