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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:56:31  来源:igfitidea点击:

How do I listen for scrolling in a ListView?

c#winformslistview

提问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 ListViewis scrolled, the position of the items change. If we check for a change in the first ListViewItem's Boundsproperty, we can track whether movement has occurred.

我们依赖于这样一个事实,即当ListView滚动时,项目的位置会发生变化。如果您在第一个变化ListViewItemBounds属性,我们可以追踪是否发生移动。

You'll need to add a Timercontrol to the same form your ListViewis on and set its Enabledproperty to True(this means that it will fire regularly without having to be Started). 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 Tickevent:

然后为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 Intervalof 100ms seems to work fine for me, but you may need to tweak this to suit your application.

Timer Interval100 毫秒的默认值对我来说似乎工作正常,但您可能需要调整它以适合您的应用程序。

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.

现在它在列表视图中的所有滚动事件中重新显示。