Windows 10 ScrollIntoView() 不会滚动到列表视图中间的项目

2024-05-06

我有一个包含 20 个项目的列表视图。我想以编程方式滚动列表视图。

ListView?.ScrollIntoView(ListView.Items[0])

将滚动列表视图到第一项。

ListView?.ScrollIntoView(ListView.Items.Count - 1)

会将列表视图滚动到页面底部。

但是,我无法使用相同的函数将列表视图滚动到中间的项目。

Eg: ListView?.ScrollIntoView(ListView.Items[5])

应该滚动并带我到列表的第五项。但它却把我带到了列表的第一项。

如果可以通过一些解决方法来实现这种行为,那就太好了?


我认为你正在寻找的是一种实际上的方法scroll一个元素到顶部ListView.

In 这个帖子 https://stackoverflow.com/questions/32190237/how-to-scroll-to-element-in-uwp/32193216#32193216,我创建了一个扩展方法,可以滚动到 a 中的特定元素ScrollViewer.

你的想法是一样的。

您需要首先找到ScrollViewer您的实例中的ListView,然后是要滚动到的实际项目,即ListViewItem.

这是一个扩展方法来获取ScrollViewer.

public static ScrollViewer GetScrollViewer(this DependencyObject element)
{
    if (element is ScrollViewer)
    {
        return (ScrollViewer)element;
    }

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
    {
        var child = VisualTreeHelper.GetChild(element, i);

        var result = GetScrollViewer(child);
        if (result == null)
        {
            continue;
        }
        else
        {
            return result;
        }
    }

    return null;
}

一旦我得到ScrollViewer例如,我创建了另外两个扩展方法来分别根据其索引或附加对象滚动到项目。自从ListView and GridView共享相同的基类ListViewBase。这两种扩展方法也应该适用于GridView.

Update

基本上,这些方法将首先找到该项目(如果它已经呈现),然后立即滚动到它。如果该项目是null,表示虚拟化已开启,该项目尚未实现。因此,要首先实现该项目,请调用ScrollIntoViewAsync(基于任务的方法来包装内置ScrollIntoView, 与...一样ChangeViewAsync,它提供了更清晰的代码),计算位置并保存它。既然现在我知道要滚动到的位置,我需要首先将项目一直滚动回其先前的位置即刻(即没有动画),然后最后滚动到有动画的所需位置。

public async static Task ScrollToIndex(this ListViewBase listViewBase, int index)
{
    bool isVirtualizing = default(bool);
    double previousHorizontalOffset = default(double), previousVerticalOffset = default(double);

    // get the ScrollViewer withtin the ListView/GridView
    var scrollViewer = listViewBase.GetScrollViewer();
    // get the SelectorItem to scroll to
    var selectorItem = listViewBase.ContainerFromIndex(index) as SelectorItem;

    // when it's null, means virtualization is on and the item hasn't been realized yet
    if (selectorItem == null)
    {
        isVirtualizing = true;

        previousHorizontalOffset = scrollViewer.HorizontalOffset;
        previousVerticalOffset = scrollViewer.VerticalOffset;

        // call task-based ScrollIntoViewAsync to realize the item
        await listViewBase.ScrollIntoViewAsync(listViewBase.Items[index]);

        // this time the item shouldn't be null again
        selectorItem = (SelectorItem)listViewBase.ContainerFromIndex(index);
    }

    // calculate the position object in order to know how much to scroll to
    var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content);
    var position = transform.TransformPoint(new Point(0, 0));

    // when virtualized, scroll back to previous position without animation
    if (isVirtualizing)
    {
        await scrollViewer.ChangeViewAsync(previousHorizontalOffset, previousVerticalOffset, true);
    }

    // scroll to desired position with animation!
    scrollViewer.ChangeView(position.X, position.Y, null);
}

public async static Task ScrollToItem(this ListViewBase listViewBase, object item)
{
    bool isVirtualizing = default(bool);
    double previousHorizontalOffset = default(double), previousVerticalOffset = default(double);

    // get the ScrollViewer withtin the ListView/GridView
    var scrollViewer = listViewBase.GetScrollViewer();
    // get the SelectorItem to scroll to
    var selectorItem = listViewBase.ContainerFromItem(item) as SelectorItem;

    // when it's null, means virtualization is on and the item hasn't been realized yet
    if (selectorItem == null)
    {
        isVirtualizing = true;

        previousHorizontalOffset = scrollViewer.HorizontalOffset;
        previousVerticalOffset = scrollViewer.VerticalOffset;

        // call task-based ScrollIntoViewAsync to realize the item
        await listViewBase.ScrollIntoViewAsync(item);

        // this time the item shouldn't be null again
        selectorItem = (SelectorItem)listViewBase.ContainerFromItem(item);
    }

    // calculate the position object in order to know how much to scroll to
    var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content);
    var position = transform.TransformPoint(new Point(0, 0));

    // when virtualized, scroll back to previous position without animation
    if (isVirtualizing)
    {
        await scrollViewer.ChangeViewAsync(previousHorizontalOffset, previousVerticalOffset, true);
    }

    // scroll to desired position with animation!
    scrollViewer.ChangeView(position.X, position.Y, null);
}

public static async Task ScrollIntoViewAsync(this ListViewBase listViewBase, object item)
{
    var tcs = new TaskCompletionSource<object>();
    var scrollViewer = listViewBase.GetScrollViewer();

    EventHandler<ScrollViewerViewChangedEventArgs> viewChanged = (s, e) => tcs.TrySetResult(null);
    try
    {
        scrollViewer.ViewChanged += viewChanged;
        listViewBase.ScrollIntoView(item, ScrollIntoViewAlignment.Leading);
        await tcs.Task;
    }
    finally
    {
        scrollViewer.ViewChanged -= viewChanged;
    }
}

public static async Task ChangeViewAsync(this ScrollViewer scrollViewer, double? horizontalOffset, double? verticalOffset, bool disableAnimation)
{
    var tcs = new TaskCompletionSource<object>();

    EventHandler<ScrollViewerViewChangedEventArgs> viewChanged = (s, e) => tcs.TrySetResult(null);
    try
    {
        scrollViewer.ViewChanged += viewChanged;
        scrollViewer.ChangeView(horizontalOffset, verticalOffset, null, disableAnimation);
        await tcs.Task;
    }
    finally
    {
        scrollViewer.ViewChanged -= viewChanged;
    }
}

更简单的方法,但没有动画

您还可以使用新的重载ScrollIntoView通过指定第二个参数来确保项目在顶部边缘对齐;但是,这样做并没有我以前的扩展方法中的平滑滚动过渡。

MyListView?.ScrollIntoView(MyListView.Items[5], ScrollIntoViewAlignment.Leading);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows 10 ScrollIntoView() 不会滚动到列表视图中间的项目 的相关文章

随机推荐

  • 如何BSWAP 64位寄存器的低32位?

    我一直在寻找如何将 BSWAP 用于 64 位寄存器的低 32 位子寄存器的答案 例如 0x0123456789abcdef位于 RAX 寄存器内 我想将其更改为0x01234567efcdab89用一条指令 因为性能 所以我尝试了以下内联
  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include
  • iOS 中的随机颜色

    我想让我的导航栏每次加载时都具有不同的颜色 我在 viewDidApear 中放置了以下代码 CGFloat hue arc4random 256 256 0 0 0 to 1 0 CGFloat saturation arc4random
  • JQuery 从 Div 中抓取文本减去子元素[重复]

    这个问题在这里已经有答案了 有没有一种简单的方法可以从这个 div 中获取文本而不获取任何子元素 div strong Title Text Unwanted strong This is the text I need div 我知道我可
  • Chrome 无法识别我对 javascript 文件的更改并加载旧代码?

    我在这里坐了将近一个小时来测试我正在构建的网站 由于我想查看代码中的新更改 因此我重新加载了代码 但它正在重新加载旧代码 我打开了 devetools 进行硬重新加载和清空缓存硬重新加载 它们都加载我的旧代码 我进入隐身模式 它做了同样的事
  • 检测 Android 中 OSM Mapview 是否仍在加载

    我已将 Open Street Maps 包含在我的 Android 应用程序中 在地图视图中 用户应该能够在地图完全加载后捕获屏幕 但目前 即使地图视图仍在加载 用户也可以捕获图像 有人可以告诉我如何检测地图视图何时完全加载吗 下面是我加
  • 将 dataGridView 绑定到绑定列表并按文本框过滤行

    我正在开发一个 Winforms 应用程序 并且有一个已经绑定到 dataGridView 的对象的 BindingList 我还有一个 过滤器 文本框 如果它们与文本框文本不匹配 我想从 datagridview 行中过滤掉行 我想以某种
  • 更改 RabbitMQ 队列中的参数

    我有一个 RabbitMQ 队列 最初声明如下 var result channel QueueDeclare NewQueue true false false null 我正在尝试添加死信交换 因此我将代码更改为 channel Exc
  • 从字符串渲染 React 组件

    我在字符串中有一些 React 代码 例如 const component function App return div test div 我希望能够从浏览器内渲染该组件 例如 import React Component from re
  • 如何使用 Solr 索引 pdf 内容?

    我正在尝试使用 SolrJ 索引一些 pdf 文档 如下所述http wiki apache org solr ContentStreamUpdateRequestExample http wiki apache org solr Cont
  • 如何测试抽象类的受保护抽象方法?

    我一直在研究测试名为的抽象类的最佳方法TabsActionFilter 我保证继承自的类TabsActionFilter将有一个名为GetCustomer 在实践中 这种设计似乎效果很好 我遇到的一些问题是弄清楚如何测试OnActionEx
  • 如何在 Mac OS X 上的 postgres 中安装 tablefunc?

    我使用 StackBuilder 在我的 Mac OS X 计算机上安装 Postgres 9 2 现在需要使用tablefunc 貌似该功能不可用 如何在 Mac 上安装 contrib 包 正如 a horse with no name
  • 如何在 Ruby 中使用全局变量或常量值?

    我有一个看起来像这样的程序 offset Point new 100 200 def draw point pointNew offset point drawAbsolute point end draw Point new 3 4 指某
  • 获取数组的第一个元素

    我有一个数组 array 4 gt apple 7 gt orange 13 gt plum 我想获取这个数组的第一个元素 预期结果 字符串apple 要求一 它不能通过引用传递来完成 so array shift这不是一个好的解决方案 我
  • Perl:避免从标准输入贪婪读取?

    考虑以下 perl 脚本 read pl my line
  • 单个函数的 Numpy 均值和方差?

    使用 Numpy Python 是否可以从单个函数调用返回均值 AND 方差 我知道我可以单独做它们 但是计算样本标准差需要平均值 因此 如果我使用单独的函数来获取均值和方差 则会增加不必要的开销 我尝试在这里查看 numpy 文档 htt
  • 在开始工作之前忘记在 GitHub 上进行 fork

    假设我将 C 公司的 X 项目存储库从 github 克隆到我的本地计算机 我在本地为自己创建一个分支 对其进行一些工作并在本地提交到我的分支 现在我想向 C 公司发出拉取请求 但我意识到我应该在 gitub 上进行分叉以创建我自己的项目
  • Calendar.getActualMaximum(Calendar.WEEK_OF_YEAR) 怪异

    要么我不明白这个方法getActualMaximum int 或字段 WEEK OF YEAR 或者涉及 Sun bug 或全部三个 有人可以向我解释为什么吗 至少在德国语言环境中 以下代码 Locale setDefault Locale
  • Spring Cloud AWS 与 Transfermanager:无法完成传输:连接池关闭

    我在用Spring Boot 1 5 1 RELEASE with 春季云AWS 1 1 3 RELEASE将文件上传到 AWS S3 存储桶 我想用转账管理器 http docs aws amazon com AWSJavaSDK lat
  • Windows 10 ScrollIntoView() 不会滚动到列表视图中间的项目

    我有一个包含 20 个项目的列表视图 我想以编程方式滚动列表视图 ListView ScrollIntoView ListView Items 0 将滚动列表视图到第一项 ListView ScrollIntoView ListView I