Domanda

Questa sembra una domanda fondamentalmente semplice. Ho una finestra di dialogo WinForms con una casella di riepilogo. Questo controllo è non compilato tramite associazione di dati ma è pieno di chiamate a

listBox.Items.Add (obj);

È possibile che questa chiamata possa essere effettuata in modo asincrono da varie posizioni e vorrei agganciare la casella di riepilogo e cercare le modifiche nei suoi membri di dati in modo da poter eseguire altre modifiche dell'interfaccia utente (come abilitare o disabilitare i controlli che interagiscono con la casella di riepilogo in base al numero di elementi nell'elenco).

Sfortunatamente, a meno che non sia completamente all'oscuro, non sembra esserci un evento o un metodo virtuale che possa essere agganciato per rilevare questo. Posso agganciare le modifiche selezionate e (per CheckedListBox) posso agganciare le modifiche dello stato di controllo. Ma non per le modifiche alla raccolta di dati sottostanti.

So che questo è possibile in Win32 (c'è un messaggio finestra per questo). Cosa mi sto perdendo?


[A cura di Simone]

Soluzione

Mi è stata indicata la soluzione corretta (che ho contrassegnato come risposta accettata) che è quella di sovrascrivere il metodo WndProc di ListBox e gestire manualmente i messaggi di listbox. Ecco la soluzione su cui ho optato (e funziona). Potrebbe essere modificato per fornire maggiori dettagli nell'evento o dividere i messaggi in eventi separati, ma per le mie esigenze è sufficiente.

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 { };
}
È stato utile?

Soluzione

Non conosco alcun evento che puoi guardare per mostrare che un elemento è stato aggiunto a un ListBox. Forse puoi usare invece il metodo Win32 che hai descritto (ad esempio, prendi un handle, usa WndProc, ecc.).

In alternativa, forse puoi usare un'altra classe che invece aggiunge elementi. Ad esempio, anziché chiamare direttamente il metodo Add su ListBox, è possibile che le azioni dell'utente chiamino il metodo Add all'interno della nuova classe che quindi aggiunge l'elemento a ListBox. Potresti organizzare un evento all'interno di quella classe che ti consenta di vedere cosa è stato aggiunto.

Mi piace anche l'idea di sottoclassare ListBox come menzionato da un altro poster ....

Altri suggerimenti

Ecco un post su un altro forum che consiglia di creare una classe figlio che includa quel comportamento.

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

Questa soluzione sembra funzionare - nella mia situazione, l'ho implementata in VB. Ho appena creato una classe ExtendedListbox che eredita il controllo listbox, implementa INotifyPropertyChanged e ombreggia la proprietà 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

Sfortunatamente, non esiste un modo semplice per farlo utilizzando l'ereditarietà o gli eventi. Dovresti essere in grado di sovrascrivere il metodo Add della classe Items, ma non ci riesci! Potresti essere in grado di intercettare il ciclo di messaggi per capire quando sta accadendo, ma questo va oltre la mia esperienza.

Una cosa che ho notato dalla tua domanda è che dici che gli articoli vengono aggiunti in modo asincrono. Non farlo. Il tuo problema potrebbe essere risolto se ti sincronizzi sul thread del form (se il tuo problema è che il controllo non si aggiorna).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top