Domanda

Mi sono messo in un angolo qui.

Ho una serie di UserControls che ereditano da un genitore, che contiene un paio di metodi ed eventi per semplificare le cose in modo da non dover scrivere righe e righe di codice quasi identico.Come fai tu.Il genitore non contiene altri controlli.

Quello che voglio fare è avere solo un gestore di eventi, nell'UserControl genitore, che va e fa cose che solo il controllo genitore può fare (cioè chiamare in modo condizionale un evento, come definito dall'evento nel genitore).Collegherei quindi questo gestore di eventi a tutte le caselle di input nei miei controlli figlio e i controlli figlio risolverebbero il compito di analizzare l'input e dire al controllo genitore se lanciare quell'evento.Codice bello e pulito, senza ripetizioni, copia-incolla (che per me Sempre risulta in un bug).

Ecco la mia domanda.Visual Studio pensa che io sia troppo intelligente della metà e mi avverte che "il metodo" checkreadessiness [il gestore di eventi nel genitore] non può essere il metodo per un evento perché una classe questa classe deriva da già definisce il metodo". Sì, Visual Studio, questo è il punto.IO Volere avere un gestore di eventi che gestisca solo gli eventi generati dalle classi figlie e il suo unico compito è consentirmi di collegare i figli senza dover scrivere una singola riga di codice.Non ho bisogno di quei gestori aggiuntivi: tutte le funzionalità di cui ho bisogno vengono naturalmente chiamate mentre i bambini elaborano l'input dell'utente.

Non sono sicuro del motivo per cui Visual Studio abbia iniziato a lamentarsi di questo ora (poiché me lo permetteva prima) e non sono sicuro di come risolverlo.Preferibilmente, mi piacerebbe farlo senza dover definire un metodo che chiami semplicemente CheckReadiness.Cosa sta causando questo avviso, cosa lo sta facendo apparire ora mentre non lo era un'ora fa, e come posso farlo sparire senza ricorrere alla creazione di piccoli gestori in tutte le classi infantili?

È stato utile?

Soluzione

Dichiara virtuale il metodo genitore, sovrascrivilo nelle classi figlie e chiama

base.checkReadyness(sender, e);

(o sua derivazione) dall'interno della classe infantile.Ciò consente l'evoluzione futura del design, ad esempio se si desidera eseguire un codice specifico di controllo degli errori prima di chiamare il gestore eventi padre.Potrebbe non essere necessario scrivere milioni di gestori di eventi come questo per ciascun controllo, potresti semplicemente scriverne uno, collegare tutti i controlli a questo gestore di eventi che a sua volta chiama il gestore di eventi del genitore.

Una cosa che ho notato è che se tutto questo codice viene inserito all'interno di una DLL, potresti riscontrare un calo delle prestazioni tentando di chiamare un gestore eventi dall'interno di una DLL.

Altri suggerimenti

Mi sono appena imbattuto anche in questo, sono d'accordo che sembra che tu stia facendo tutto correttamente.Dichiarare il metodo virtuale è nella migliore delle ipotesi una soluzione alternativa, non una soluzione.

Ciò che viene fatto è valido: un controllo che esiste solo nella classe derivata e la classe derivata allega un gestore di eventi a uno degli eventi di quel controllo.Il fatto che il metodo che gestisce l'evento sia definito nella classe base non è né qui né lì, è disponibile nel momento del collegamento all'evento.L'evento non viene allegato due volte o qualcosa del genere, è semplicemente una questione di dove viene definito il metodo che gestisce l'evento.

Sicuramente non è un metodo virtuale: non voglio che il metodo sia sovrascrivibile da una classe derivata.Molto frustrante e, secondo me, un bug in dev-studio.

Anch'io ho riscontrato questo problema perché nelle versioni precedenti di VS potevi "ereditare" i gestori di eventi.Quindi la soluzione che ho trovato senza dover sovrascrivere i metodi è semplicemente quella di assegnare il gestore eventi da qualche parte nella fase di inizializzazione del modulo.Nel mio caso, fatto nel costruttore (sono sicuro che anche OnLoad() funzionerebbe):

    public MyForm()
    {
        InitializeComponent();
        btnOK.Click += Ok_Click;
    }

...dove risiede il gestore Ok_Click nel modulo base.Cibo per la mente.

Mi sono appena imbattuto nello stesso problema sollevato per primo da Merus e, come altri che hanno pubblicato risposte, non mi è del tutto chiaro il motivo per cui VS (ora sto utilizzando Visual C# 2010 Express) obietta di avere il gestore eventi definito nella base classe.Il motivo per cui sto postando una risposta è che nel tentativo di aggirare il problema rendendo il codice della classe base un metodo protetto che le classi derivate invocano semplicemente nei loro gestori di eventi (essenzialmente vuoti), ho rinominato il refactoring della base class e ho notato che il progettista VS ha smesso di lamentarsi.Cioè, ha rinominato la registrazione del gestore eventi (quindi non ha più seguito la convenzione del progettista VS di denominare i gestori eventi con ControlName_EventName) e questo sembrava soddisfarlo.Quando ho quindi provato a registrare il gestore eventi di base (ora rinominato) rispetto ai controlli della classe derivata inserendo il nome nell'evento VS appropriato, il progettista ha creato un nuovo gestore eventi nella classe derivata che ho poi eliminato, lasciando registrato il controllo della classe derivata al metodo della classe base (gestore eventi).Net, come ci si aspetterebbe, C# trova legittimo ciò che vogliamo fare.È solo al progettista VS che non piace quando si segue la convenzione di denominazione del gestore eventi del progettista.Non vedo la necessità che il designer lavori in questo modo.Comunque, è ora di andare avanti.

Se il tuo evento è già definito nella classe genitore, non è necessario ricablarlo nuovamente nella classe figlio.Ciò farà sì che l'evento si attivi due volte.

Verifica se questo è ciò che sta accadendo.HTH :)

Questo articolo su MSDN dovrebbe essere un buon punto di partenza: Sostituzione dei gestori eventi con Visual Basic .NET.Dai un'occhiata a Come la clausola Handles può causare problemi nella classe derivata sezione.

Perché non dichiarare il metodo come virtuale nella classe genitore e quindi poterlo sovrascrivere nelle classi derivate per aggiungere funzionalità extra?

Dimentica che si tratta di un gestore di eventi ed esegui semplicemente l'override regolare del metodo nella classe figlia.

Ecco cosa ho fatto per richiamare i metodi di base in diverse forme dall'aspetto simile, ognuna delle quali ha alcune funzionalità extra rispetto a quelle comuni:

        protected override void OnLoad(EventArgs e)
    {
        try
        {
            this.SuspendLayout();
            base.OnLoad(e);

            foreach (Control ctrl in Controls)
            {
                Button btn = ctrl as Button;
                if (btn == null) continue;

                if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnAdd_Click);
                else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnEdit_Click);
                else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnDelete_Click);
                else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnPrint_Click);
                else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnExport_Click);
            }

La possibilità di omettere l'utilizzo del nome del pulsante fisso corretto mi sembra uguale alla possibilità di non collegare manualmente il gestore ereditato.

Tieni presente che potrebbe essere necessario testare this.DesignMode in modo da saltare del tutto il codice in VS Designer, ma per me funziona bene anche senza il controllo.

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