代码之家  ›  专栏  ›  技术社区  ›  Simon Gillbee

如何检测项是否添加到ListBox(或CheckedListBox)控件中

  •  21
  • Simon Gillbee  · 技术社区  · 15 年前

    这似乎是一个非常简单的问题。我有一个WinForms对话框和一个列表框。这种控制是 通过数据绑定填充,但填充了对

    listBox.Items.Add (obj);
    

    可以从不同的位置异步进行此调用,我希望挂接列表框并监视其数据成员中的更改,以便执行其他UI更改(例如,根据列表中的项目数启用或禁用与列表框交互的控件)。

    不幸的是,除非我完全没有头绪,否则似乎没有一个事件或虚拟方法可以被钩住来检测这一点。我可以挂接选择更改,并且(对于checkedlistbox)可以挂接检查状态更改。但不适用于对基础数据集合的更改。

    我知道这在Win32中是可能的(这有一个窗口消息)。我错过了什么?


    [西蒙编辑]

    解决方案

    我指出了正确的解决方案(我已将其标记为接受的答案),即重写列表框的wndProc方法并手动处理列表框消息。这是我解决(和工作)的方法。可以修改它以在事件中提供更多详细信息,或者将消息拆分为单独的事件,但对于我的需要,这就足够了。

    using System;
    using System.Windows.Forms;
    
    public class CheckedListBoxEx : CheckedListBox
    {
        public CheckedListBoxEx() { }
    
        private const int LB_ADDSTRING = 0x180;
        private const int LB_INSERTSTRING = 0x181;
        private const int LB_DELETESTRING = 0x182;
        private const int LB_RESETCONTENT = 0x184;
    
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == LB_ADDSTRING ||
                m.Msg == LB_INSERTSTRING ||
                m.Msg == LB_DELETESTRING ||
                m.Msg == LB_RESETCONTENT)
            {
                ItemsChanged(this, EventArgs.Empty);
            }
            base.WndProc(ref m);
        }
    
        public event EventHandler ItemsChanged = delegate { };
    }
    
    4 回复  |  直到 8 年前
        1
  •  7
  •   Michael Todd    15 年前

    我不知道有什么活动可以让你看出来一个项目已经添加到列表框中。也许您可以使用您描述的win32方法(即抓取一个句柄,使用wndproc等)。

    或者,您可以使用另一个类来添加项。例如,不直接调用列表框上的添加方法,而是让用户操作调用新类内的添加方法,然后将该项添加到列表框中。您可以在该类中设置一个事件,允许您查看添加的内容。

    我也喜欢另一张海报提到的列表框子类化的想法……

        2
  •  3
  •   Kevin Laity    15 年前

    这是另一个论坛上的帖子,建议创建一个包含这种行为的儿童班。

    http://www.eggheadcafe.com/forumarchives/netframeworkcompactframework/jul2005/post23265940.asp

        3
  •  1
  •   mbm29414    8 年前

    这个解决方案似乎有效——在我的情况下,我是用VB实现的。我刚刚创建了一个extendedListBox类,它继承了ListBox控件,实现了inotifyPropertyChanged,并隐藏了items属性。

    Imports System.ComponentModel
    
    Public Class ExtendedListBox:Inherits ListBox:Implements INotifyPropertyChanged
    
        Public Shadows Property Items() As ObjectCollection
            Get
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Items"))
                Return MyBase.Items
            End Get
            Set(value As ObjectCollection)
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Items"))
                MyBase.Items.Clear()
                For Each o As Object In value
                    MyBase.Items.Add(o)
                Next
            End Set
        End Property
    
        Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    End Class
    
        4
  •  0
  •   Michael Meadows    15 年前

    不幸的是,使用继承或事件实现这一点并不容易。您应该能够重写items类的add方法,但是您不能访问它!您可能能够截获消息循环,以确定这是什么时候发生的,但这超出了我的经验。

    我从您的问题中注意到的一件事是,您提到的项是异步添加的。别那么做。如果在窗体线程上进行同步(如果问题是控件没有更新),则问题可能会得到解决。