Как прослушать прокрутку в ListView? - PullRequest
1 голос
/ 16 декабря 2008

Кажется, что ListView не поддерживает событие Scroll. Мне нужно вызывать функцию всякий раз, когда список прокручивается; как бы я пошел по этому поводу?

Ответы [ 3 ]

6 голосов
/ 17 декабря 2008

Зачем вам вызывать функцию при прокрутке списка?

Если вы изменяете элементы по мере их прокрутки, я бы порекомендовал установить виртуальный просмотр списка.

Или вы можете переопределить просмотр списка и сделать это:

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();
    }
}
4 голосов
/ 05 августа 2010

кажется, лучший подход - это решение Брайана. Тем не менее, он реагирует только на события, генерируемые полосами прокрутки, а не на события от средней кнопки мыши.

если вы измените условное выражение:

   if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL) 
             this.OnScroll();

по:

   if (m.Msg == 0x000c2c9) 
             this.OnScroll();

теперь он передается на всех событиях прокрутки в просмотре списка.

0 голосов
/ 17 декабря 2008

Вот решение, которое учитывает каждый из режимов отображения ListView:

Мы полагаемся на то, что при прокрутке ListView положение элементов меняется. Если мы проверим изменение первого свойства ListViewItem Bounds, мы сможем отследить, произошло ли движение.

Вам нужно будет добавить элемент управления Timer в ту же форму, в которой включен ListView, и установить для его свойства Enabled значение True (это означает, что он будет срабатывать регулярно, не будучи Start ред). Также добавьте приватную переменную в свой класс формы, чтобы записать первый элемент Bounds.

private Rectangle _firstItemBounds = null;

Когда вы заполняете 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;
}

Затем добавьте обработчик для события Timer Tick:

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
        // ...
    }
}

Кажется, что по умолчанию Timer Interval 100 мс работает нормально, но вам, возможно, потребуется настроить его в соответствии с вашим приложением.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...