Winforms ListView TopItem改变了事件?

时间:2012-01-09 16:54:20

标签: c# .net winforms listview

当win表单的listview首项属性更改时,是否有任何事件触发?

2 个答案:

答案 0 :(得分:2)

您需要一个Scroll事件来检测TopItem可能已更改。 ListView没有。这可能是故意的,该类包含一些解决本机Windows控件中的错误的黑客攻击,使用滚动的黑客攻击。

然而,在您的情况下,这些黑客应该无关紧要,因为您只需要查找TopItem中的更改。您将要覆盖WndProc()方法,以便获取LVN_ENDSCROLL消息。这很好用,虽然我没有彻底测试。在项目中添加一个新类并粘贴下面的代码。编译。将新控件从工具箱顶部拖放到表单上。实现TopItemChanged事件。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class MyListView : ListView {
    public event EventHandler TopItemChanged;

    protected virtual void OnTopItemChanged(EventArgs e) {
        var handler = TopItemChanged;
        if (handler != null) handler(this, e);
    }

    protected override void WndProc(ref Message m) {
        // Trap LVN_ENDSCROLL, delivered with a WM_REFLECT + WM_NOTIFY message
        if (m.Msg == 0x204e) {
            var notify = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
            if (notify.code == -181 && !this.TopItem.Equals(lastTopItem)) {
                OnTopItemChanged(EventArgs.Empty);
                lastTopItem = this.TopItem;
            }
        }
        base.WndProc(ref m);
    }

    private ListViewItem lastTopItem = null;
    private struct NMHDR {
        public IntPtr hwndFrom;
        public IntPtr idFrom;
        public int code;
    }
}

答案 1 :(得分:1)

TopItem属性没有专门的事件。但是,您应该能够通过缓存上一个TopItem结果并将其与其他事件进行比较来获得相同的效果,这些事件是项目重新排序的指标:例如PaintDrawItem

private void WatchTopItemChanged(ListView listView, Action callOnChanged) {
  var lastTopItem = listView.TopItem;
  listView.DrawItem += delegate {
    if (lastTopItem != listView.TopItem) {
      lastTopItem = listView.TopItem;
      callOnChanged();
    }
  };
}