代码之家  ›  专栏  ›  技术社区  ›  Hank

在TabControl选项卡项之间切换时捕获和设置DataGrid滚动位置

  •  1
  • Hank  · 技术社区  · 8 年前

    我有 TabControl 这有一个 DataGrid TabItem VirtualizingPanel ScrollUnit Pixel ,所以滚动有点自然。

    在选项卡项之间切换时,行选择行为正常。但是,在数据网格的 ScrollViewer 所以它的位置和你离开时完全一样 标签项目 工作不正常。

    目前的工作方式是,我在 数据网格 Scrollviewer ScrollChangedEvent 它保存了 VerticalOffset . 更换为新的 然后换回原样 标签项目 DataContextChanged 垂直偏移 保存到 垂直偏移

    public class DataGridBehaviors : Behavior<DataGrid>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.DataContextChanged += DataGrid_DataContextChanged;
            this.AssociatedObject.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(DataGridScrollViewer_ScrollChanged));
        }
    
        protected override void OnDetaching()
        {
            Console.WriteLine("OnDetaching");
            this.AssociatedObject.RemoveHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(DataGridScrollViewer_ScrollChanged));
            this.AssociatedObject.DataContextChanged -= DataGrid_DataContextChanged;
            base.OnDetaching();
        }
    
        private void DataGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            ModuleGeometry oldModuleGeometry = (ModuleGeometry)e.OldValue;
            ModuleGeometry newModuleGeometry = (ModuleGeometry)e.NewValue;
            ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(this.AssociatedObject);
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToVerticalOffset(newModuleGeometry.VerticalScrollPosition);
            }
        }
    
        private void DataGridScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ModuleGeometry modGeom = (ModuleGeometry)this.AssociatedObject.DataContext;
            modGeom.VerticalScrollPosition = e.VerticalOffset;
        }
    
        private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
        {
            T child = default(T);
    
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }
    }
    

    所发生的事情是向下滚动,顶部的DataGridRow部分显示(您只能看到它的一半)。然后,当您在两个选项卡项之间切换时,程序会正确设置垂直偏移,但随后会再次自动重置到部分显示行的顶部(完全显示)。

    切换前。将垂直偏移保存为4327.2 enter image description here enter image description here

    当你在VirtualizingPanel中加载了一个扩展的行时,情况变得更为奇怪,跳转更为剧烈。

    enter image description here 切换回原始选项卡项后 enter image description here

    我希望看到滚动位置与我离开时的位置完全相同,我如何才能做到这一点?

    1 回复  |  直到 8 年前
        1
  •  1
  •   mm8    8 年前

    最简单的方法可能是停止 TabControl

    有关详细信息,请参阅以下链接。

    How to stop Wpf Tabcontrol to unload Visual tree on Tab change

    WPF - Elements inside DataTemplate property issue when no binding?