【问题标题】:Keep scroll position with virtualized datagrid使用虚拟化数据网格保持滚动位置
【发布时间】:2018-05-31 11:18:15
【问题描述】:

我有一个小问题。我有一个数据网格,它显示很多行。因此,为了提高性能,我决定虚拟化我的数据网格。 到此为止,没问题。现在,我想在刷新后保持滚动位置。

尽管进行了一些研究,但我没有找到解决方案。 这是我现在的代码,但是,它不起作用:

 <DataGrid x:Name="Test" AutoGenerateColumns="False" ItemsSource="{Binding ItemCollection}" SelectionMode="Single"  IsReadOnly="True"
                         CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
                         SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                         VirtualizingPanel.IsVirtualizingWhenGrouping="True" VirtualizingPanel.IsContainerVirtualizable="True"
                         VirtualizingPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" Grid.Row="1"
                         ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled">

在我的 ViewModel 中,我像这样刷新我的数据网格:

public ICollectionView ItemCollection
{
    get
    {
        return _itemCollection;
    }
    set
    {
        _itemCollection= value;
        OnPropertyChanged(() => ItemCollection);
    }
} 

这是我刷新数据网格集合的函数:

var orderCollection = Items.OrderByDescending(item => item.BeginDate);

var itemCollection = CollectionViewSource.GetDefaultView(orderCollection);
itemCollection.GroupDescriptions.Clear();

using (itemCollection.DeferRefresh())
{
    itemCollection.GroupDescriptions.Add(new PropertyGroupDescription("ShortStartDate"));
    itemCollection.Filter = ApplyFilter;
}

ItemCollection = itemCollection;

还有这个,我的代码。在调用上述方法之前调用 GetScrollPosition。之后调用 SetScrollPosition。

private void GetScrollPosition()
{
    if (DayBooks != null)
    {
        var scrollViewer = GetScrollViewer(DayBooks);
        if (scrollViewer != null)
            _currentScrollPosition = scrollViewer.VerticalOffset;
    }
}

public void SetScrollPosition()
{
    if (Test != null)
    {
        var scrollViewer = GetScrollViewer(Test);
        if (scrollViewer != null)
        {
            if (_currentScrollPosition != 0)
            {
                scrollViewer.InvalidateScrollInfo();
                scrollViewer.ScrollToVerticalOffset(_currentScrollPosition);
            }
        }
    }
}

private ScrollViewer GetScrollViewer(UIElement element)
{
    if (element == null) return null;

    ScrollViewer retour = null;
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element) && retour == null; i++)
    {
        if (VisualTreeHelper.GetChild(element, i) is ScrollViewer)
        {
            retour = (ScrollViewer)(VisualTreeHelper.GetChild(element, i));
        }
        else
        {
            retour = GetScrollViewer(VisualTreeHelper.GetChild(element, i) as UIElement);
        }
    }
    return retour;
}

所以,当我的数据网格更新时,我尝试设置我的滚动位置 (_currentScrollPosition),但位置保持为 0,我失去了位置。

是否有可能解决我的问题并保持我的虚拟化进程?

【问题讨论】:

  • 我已经编辑了我的问题...这一行,scrollViewer.ScrollToVerticalOffset(_currentScrollPosition);对我的数据网格没有影响! resfresh 后,我的数据网格滚动位置保持为 0,并且在刷新后丢失了我的位置
  • 如何“刷新”DataGrid?您的问题中缺少这部分。
  • 问题再次更新。对不起;)
  • 实际调用 GetScrollViewer 的时间和地点?您应该阅读以下内容:stackoverflow.com/help/mcve
  • 我再次编辑了我的帖子。希望我的问题没问题

标签: c# wpf


【解决方案1】:

您的问题通常通过滚动到视图行为来解决,该行为对选定项而不是某个 scoll 位置作出反应: ScrollIntoView for WPF DataGrid (MVVM)

您是否考虑过使用这样的行为来实现您正在寻找的行为?

【讨论】:

  • ScrollIntoView 方法有效。但问题是,用户必须单击才能保持数据网格中的位置。他们更喜欢滚动,如果数据网格被刷新,保持他们的位置!
  • 但是,我会尝试用 ScrollToVerticalOffset 方法和行为来做同样的事情。也许……
猜你喜欢
  • 2021-02-16
  • 1970-01-01
  • 2010-12-22
  • 2014-07-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 2018-04-08
  • 1970-01-01
相关资源
最近更新 更多