繁体   English   中英

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

[英]How to detect if items are added to a ListBox (or CheckedListBox) control

这似乎是一个从根本上简单的问题。 我有一个带有列表框的 WinForms 对话框。 此控件不是通过数据绑定填充的,而是填充了对

listBox.Items.Add (obj);

有可能这个调用可以从不同的地方异步进行,我想挂钩列表框并观察其数据成员的变化,以便我可以执行其他 UI 更改(例如启用或禁用与基于列表框交互的控件关于列表中的项目数)。

不幸的是,除非我完全一无所知,否则似乎没有一个事件或虚拟方法可以用来检测这一点。 我可以挂钩 select 更改并且(对于 CheckedListBox)我可以挂钩检查状态更改。 但不适用于对基础数据收集的更改。

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


[西蒙编辑]

解决方案

我被指出了正确的解决方案(我已将其标记为已接受的答案),即覆盖 ListBox 的 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 { };
}

我不知道您可以观看任何显示项目已添加到 ListBox 的事件。 也许您可以改用您描述的 Win32 方法(即抓住一个句柄,使用 WndProc 等)。

或者,也许您可以使用另一个 class 来代替添加项目。 例如,您可以让用户操作在新的 class 中调用 Add 方法,而不是直接调用 ListBox 上的 Add 方法,然后将项目添加到 ListBox。 您可以在 class 中设置一个事件,让您可以查看添加的内容。

我也喜欢另一张海报提到的对 ListBox 进行子类化的想法......

这是另一个论坛上的帖子,建议创建一个包含该行为的子 class。

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

这个解决方案似乎有效 - 在我的情况下,我在 VB 中实现了它。 我刚刚创建了一个 ExtendedListbox class,它继承了列表框控件,实现了 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

不幸的是,使用 inheritance 或事件没有简单的方法来做到这一点。 您应该能够覆盖 Items class 的 Add 方法,但您无法访问它,您可能能够拦截消息循环以确定何时发生这种情况。 但这超出了我的经验。

我从您的问题中注意到的一件事是您提到项目是异步添加的。 不要那样做。 如果您在表单的线程上同步,您的问题可能会得到解决(如果您的问题是控件没有更新)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM