WinForms ListView,在重新加载时记住滚动位置
我有一个列表视图,其中填充了 8 列用户数据。 用户可以选择启用自动刷新,这会导致 ListView 被清除并使用数据库中的最新数据重新填充。
问题是,当清除并重新填充项目时,可见区域会跳回列表顶部。 因此,如果我正在查看 2000 项中的第 1000 项,则返回该项非常不方便。
基本上,我要问的是,如何获取当前的滚动距离(x 和 y)然后恢复它们?
I've got a list view that I'm populating with 8 columns of user data. The user has the option to enable auto refreshing, which causes the ListView to be cleared and repopulated with the latest data from the database.
The problem is that when the items are cleared and repopulated, the visible area jumps back to the top of the list. So if I'm looking at item 1000 of 2000, it's very inconvenient to get back to that item.
Basically, what I'm asking is, how do I get the current scroll distances (x and y) and then restore them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我只是想为那些拼命尝试使用有问题的 ListView.TopItem 属性的人提供一些信息:
不是 String.Empty,否则该属性将不起作用。
当然,这会导致ListView的滚动条跳到0又回到最上面item的位置,这就很烦人了。 如果您找到此问题的解决方法,请更新此问题。
I just wanted to provide some information for those who desperately try to use the buggy ListView.TopItem property:
than String.Empty, or the property won't work.
Of course, this will cause the ListView's scrollbar to jump to 0 and back to the location of the top item, which is annoying. Please update this question if you find a workaround to this problem.
我成功地使用了以下内容:
I used the following successfully:
不久前我遇到了同样的问题,我最终实现了一种算法来将模型与列表进行比较,所以我只添加/删除了已更改的元素。 这样,如果没有发生重大变化,列表就不会跳到开头。 我想要实现的主要目标是效率(这样列表就不会闪烁)。
I had the same problem with a while ago and I ended up implementing an algorithm to compare the model with the list, so I only added/removed elements that had changed. This way if there were no massive changes the list didn't jump to the beginning. And the main thing I wanted to achieve was the efficiency (so that the list doesn't blink).
ListView 上的 TopItemIndex 属性就是您正在寻找的内容,但是它有一些已确认的错误,这些错误应该在 VS2010 版本中得到解决。不确定(尚未检查)。
无论如何,我完成这项工作的解决方法是这样做:
出于某种原因,直接设置它不会更新它,而是将其设置为最后一项,然后我想要的项目对我来说可靠地工作。
The TopItemIndex property on ListView is what you are looking for, however it has some confirmed bugs that should have been addressed in VS2010 release.. not sure (haven't checked).
Anyway, my workaround for making this work is to do this:
For some reason setting it directly does not update it, but setting it to the last item and then the one I want works reliably for me.
查看 ListView.TopItem 属性。 它有一个索引,其中应包含其在列表中的位置。 在新列表中找到该索引,并将 TopItem 设置为该项目,它应该自动滚动。
Look at the ListView.TopItem property. It has an index, which should contain its position in the list. Find that index in the new list, and set TopItem to that item, and it should do the scrolling automatically.
不幸的是,您将需要使用一些互操作来滚动到 ListView 中的确切位置。 使用 GetScrollInfo winapi 函数获取现有的滚动位置和 SendMessage 滚动到该位置。
CodeProject 上一篇名为 Scrolling to a group with a ListView 的文章可能会指导您找到解决方案。
Unfortunately you will need to use some interop to scroll to the exact position in the ListView. Use GetScrollInfo winapi function to get the existing scroll position and SendMessage to scroll to the position.
There in an article on CodeProject named Scrolling to a group with a ListView that might guide you to the solution.
我维护滚动位置的解决方案:
表单级别变量:
在列表视图刷新(即计时器、按钮)内存储当前位置:
在refreshTheForm方法内显示存储的位置(放在方法的最末尾):
My solution to maintaining scroll position:
Form level variable:
Inside listview refresh (ie Timer,button) to store the current spot:
Inside refreshTheForm method to show the stored spot (put at very end of method):
我遇到了同样的问题。 我有一个 listView,每 1/2 秒填充一次,当我将 TopItem 设置为索引 > 的 ListItem 时,我会填充它。 可见的项目,然后列表在 topItem 和后 2 个位置之间跳转。
因此,为了纠正该问题,我在调用 EndUpdate 之后设置了 TopIterm。
I was having sort-of the same problem. I have a listView that I populate every 1/2 sec and when I set the TopItem to an ListItem whose index > visible items, then the list jumped between the topItem and back 2 spots.
So, to correct the problem, I set the TopIterm AFTER the call to EndUpdate.
在我的测试中,尽管我使用 int 来保存所选项目,但您甚至不需要 TopItem。 如果您使用 View.Tile 或 View.LargeIcon,TopItem 也会引发异常。
此代码不会移动滚动条:
In my tests, you did not even need the TopItem, although I used a int to save the selected item. Also TopItem throws an exception if you are using View.Tile or View.LargeIcon.
This code does not move the scroll bars: