23

これは根本的に単純な質問のように思えます。リストボックス付きのWinFormsダイアログボックスがあります。このコントロールは、データ バインディングによって設定されませんが、への呼び出しで満たされます。

listBox.Items.Add (obj);

この呼び出しはさまざまな場所から非同期に行うことができます。リストボックスをフックして、そのデータ メンバーの変更を監視し、他の UI 変更を実行できるようにしたいと考えています (リスト ボックス ベースの操作を有効または無効にするコントロールなど)。リスト内の項目の数)。

残念ながら、私が完全に無知でない限り、これを検出するためにフックできるイベントまたは仮想メソッドはないようです。選択の変更をフックでき、(CheckedListBox の場合) チェック状態の変更をフックできます。ただし、基になるデータ コレクションへの変更は対象外です。

これが Win32 で可能であることはわかっています (これに関するウィンドウ メッセージがあります)。私は何が欠けていますか?


[サイモン編集]

解決

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 { };
}
4

4 に答える 4

7

項目が L​​istBox に追加されたことを示すために監視できるイベントは知りません。おそらく、代わりに説明した Win32 メソッドを使用できます (つまり、ハンドルを取得する、WndProc を使用するなど)。

あるいは、代わりにアイテムを追加する別のクラスを使用することもできます。たとえば、ListBox で Add メソッドを直接呼び出すのではなく、新しいクラス内でユーザー アクションに Add メソッドを呼び出して、項目を ListBox に追加することができます。そのクラス内にイベントを設定して、追加されたものを見ることができます。

また、別のポスターで言及されているように、ListBox をサブクラス化するというアイデアも気に入っています....

于 2009-03-17T20:52:39.657 に答える
3

これは、その動作を含む子クラスの作成を推奨する別のフォーラムへの投稿です。

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

于 2009-03-17T20:49:55.793 に答える
2

このソリューションは機能しているようです-私の状況では、VBで実装しました。リストボックス コントロールを継承し、INotifyPropertyChanged を実装し、Items プロパティをシャドウする ExtendedListbox クラスを作成しました。

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
于 2015-01-30T21:31:42.047 に答える
0

残念ながら、継承やイベントを使用してこれを行う簡単な方法はありません。Items クラスの Add メソッドをオーバーライドできるはずですが、アクセスできません。メッセージループを傍受して、これがいつ起こっているかを把握できるかもしれませんが、それは私の経験を超えています.

あなたの質問から気づいたことの 1 つは、アイテムが非同期的に追加されていると述べていることです。そうしないでください。フォームのスレッドで同期すると、問題が解決する場合があります (問題がコントロールが更新されていない場合)。

于 2009-03-17T20:55:03.770 に答える