C# 如何在 ListView 中监听滚动?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/372034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I listen for scrolling in a ListView?
提问by Simon
The ListView doesn't seem to support the Scroll event. I need to call a function whenever the list is scrolled; how would I go about that?
ListView 似乎不支持 Scroll 事件。每当列表滚动时,我都需要调用一个函数;我该怎么办?
采纳答案by Brian Rudolph
Why do you need to call a function when the list is scrolled?
为什么在滚动列表时需要调用函数?
If you are changing the items as it's scrolled i would recommend setting the listview to virtual.
如果您在滚动时更改项目,我建议将列表视图设置为虚拟。
Or you could override the listview and do this:
或者您可以覆盖列表视图并执行以下操作:
public class TestListView : System.Windows.Forms.ListView
{
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
public event EventHandler Scroll;
protected void OnScroll()
{
if (this.Scroll != null)
this.Scroll(this, EventArgs.Empty);
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
this.OnScroll();
}
}
回答by Dave R.
Here's a solution that respects each of the ListView
's display modes:
这是一个尊重每个ListView
显示模式的解决方案:
We rely on the fact that as the ListView
is scrolled, the position of the items change. If we check for a change in the first ListViewItem
's Bounds
property, we can track whether movement has occurred.
我们依赖于这样一个事实,即当ListView
滚动时,项目的位置会发生变化。如果您在第一个变化ListViewItem
的Bounds
属性,我们可以追踪是否发生移动。
You'll need to add a Timer
control to the same form your ListView
is on and set its Enabled
property to True
(this means that it will fire regularly without having to be Start
ed). Also add a private variable to your form class to record the first item's Bounds
.
您需要将Timer
控件添加到您所在的同一表单ListView
并将其Enabled
属性设置为True
(这意味着它将定期触发而无需进行Start
编辑)。还要向您的表单类添加一个私有变量以记录第一项的Bounds
.
private Rectangle _firstItemBounds = null;
When you populate your ListView
, set this variable to the first item's Bounds
. For example:
填充 . 时ListView
,将此变量设置为第一个项目的Bounds
. 例如:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 1000; i++)
{
listView1.Items.Add(new ListViewItem("Item " + i));
}
_firstItemBounds = listView1.Items[0].Bounds;
}
Then add a handler for the Timer
's Tick
event:
然后为Timer
'sTick
事件添加一个处理程序:
private void timer1_Tick(object sender, EventArgs e)
{
if (listView1.Items[0] == null)
{
return;
}
Rectangle bounds = listView1.Items[0].Bounds;
if (bounds != _firstItemBounds)
{
_firstItemBounds = bounds;
// Any scroll logic here
// ...
}
}
The default Timer Interval
of 100ms seems to work fine for me, but you may need to tweak this to suit your application.
Timer Interval
100 毫秒的默认值对我来说似乎工作正常,但您可能需要调整它以适合您的应用程序。
I hope this helps.
我希望这有帮助。
回答by keimacias
it seems the best approach is the brian's solution. However, its only responds to events generated by scrollbars, but no to events from mouse midbuttton.
似乎最好的方法是布赖恩的解决方案。但是,它只响应滚动条生成的事件,而不响应来自鼠标中键的事件。
if you change the conditional:
如果您更改条件:
if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
this.OnScroll();
by:
经过:
if (m.Msg == 0x000c2c9)
this.OnScroll();
now it respods at all scrolling events in listview.
现在它在列表视图中的所有滚动事件中重新显示。