2

我需要在我的 Windows 应用程序中恢复 GridView 的滚动位置。我试图找到合适的时间来调用 ScrollViewer.ScrollToHorizo​​ntalOffset() 并让它成功。

如果我在 OnNavigatedTo 覆盖中调用它,它没有效果:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    DataContext = LoadModel();
    RestoreScrollPos();
}

如果我在页面的 Loaded 处理程序中调用它,它没有效果。

private void onPageLoaded(object sender, RoutedEventArgs e)
{
    DataContext = LoadModel();
    RestoreScrollPos();
}

如果我执行以下操作,那么它可以工作,但它很刺耳,因为 GridView 首先在滚动位置 0 处绘制,然后捕捉到新的滚动位置。

    var dontAwaitHere =
      Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
      delegate()
      {
        RestoreScrollPos();
      });

如果我尝试从默认的 Visual Studio GridView 项目中重现此行为,它似乎在大多数情况下都可以正常工作,但我确实看到它一次都不起作用。我相信存在某种竞争条件,我怀疑我把它放在错误的地方。

问题 = 我应该在哪里调用 RestoreScrollPos() 或者我应该在哪里进行调试?

    private void RestoreScrollPos()
    {
      var scrollViewer = findScrollViewer(itemGridView);
      if (scrollViewer != null)
      {
        scrollViewer.ScrollToHorizontalOffset(100000.0); // TODO test
      }
    }

    public static ScrollViewer findScrollViewer(DependencyObject el)
    {
      ScrollViewer retValue = findDescendant<ScrollViewer>(el);
      return retValue;
    }

    public static tType findDescendant<tType>(DependencyObject el)
      where tType : DependencyObject
    {
      tType retValue = null;
      int childrenCount = VisualTreeHelper.GetChildrenCount(el);

      for (int i = 0; i < childrenCount; i++)
      {
        var child = VisualTreeHelper.GetChild(el, i);
        if (child is tType)
        {
          retValue = (tType)child;
          break;
        }

        retValue = findDescendant<tType>(child);

        if (retValue != null)
        {
          break;
        }
      }

      return retValue;
    }
4

1 回答 1

0

您应该RestoreScrollPos仅在网格完成加载后调用:

public MyPageConstructor()
{
    this.InitializeComponent();
    this.itemGridView.Loaded += (s,e) => itemGridView_Loaded(s, e);
}

private void itemGridView_Loaded(object sender, RoutedEventArgs e)
{
    RestoreScrollPos();
}

至于在哪里加载数据,您应该尝试LoadState

protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    DataContext = LoadModel();
    base.LoadState(navigationParameter, pageState);
}
于 2013-06-13T12:47:59.380 回答