簡體   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