2009-06-04 13 views
6

Ho un'applicazione in C# .net che ha un MainForm e alcune classi.
Una di queste classi riceve i messaggi di dati in arrivo da una rete.
Ho bisogno di inserire il testo di questi messaggi in una casella di testo su più righe sul modulo principale.
Posso inviare il messaggio a un metodo nel MainForm rendendo il metodo statico, ma il metodo statico non può accedere ai controlli MainForm.In C# .net, come si accede a un controllo da un metodo statico?

TheIncomingDataClass.cs

namespace TheApplicationName 
{ 
    class TheIncomingDataClass 
    { 

    public void IncomingMessage(IncomingMessageType message) 
    { 
      TheApplicationName.MainForm.ReceiveMSG(message); 
    } 

MainForm.cs

public static void ReceiveMSG(string message) 
{ 
    txtDisplayMessages.AppendText(message); //This line causes compile error 
} 

L'errore di compilazione:
È necessario un riferimento oggetto per i TheApplicationName.MainForm.txtDisplayMessages nonstatic campo, metodo o proprietà' '

Qualsiasi aiuto è apprezzato.

Sono ancora un principiante del C# quindi per favore sii descrittivo.

risposta

9

Un metodo statico non ha accesso ai membri come txtDisplayMessages perché non fa parte di tale istanza. Vi suggerisco di leggere i concetti dei metodi statici e di quant'altro, perché questo è un concetto agnostico abbastanza imparziale. Sarebbe meglio servire tale metodo rimuovendo il modificatore statico, perché non ha bisogno di essere statico - sembra che avrebbe bisogno di essere chiamato da quella particolare istanza di quell'oggetto.

+0

Una volta rimossa la parola chiave statica dal metodo, non posso più chiamarla dalla classe IncomingData. Non capisco cosa intendi per "chiamato da quell'istanza particolare di quell'oggetto" potresti spiegare ulteriormente?tieni presente che ho bisogno che questi messaggi vengano inviati alla casella di testo immediatamente dopo la loro ricezione, quindi l'evento sarebbe la ricezione di un messaggio. Grazie. – timmyg

+0

Presumo poiché è statico che lo stavate chiamando con MainForm. ReceiveMSG() [o solo ReceiveMSG()]. Dovrebbe essere chiamato da un'istanza specifica di MainForm, (MainForm mf = new MainForm() o simile, per creare un'istanza). Quindi, puoi chiamarlo come mf. ReceiveMSG(), sostituendo mf con qualunque cosa hai chiamato la tua istanza di MainForm. Senza offesa, ma penso che sia necessario leggere una letteratura agnostica sull'orientamento agli oggetti, imparare cosa significa tutto questo e quindi vedere come la sintassi C# si riferisce ad essa. – Annath

+0

Seriamente, dovresti prendere CLR tramite C#. È una lettura facile (SALTA LA PRIMA COPPIA DI CAPITOLI) e va bene nei dettagli su questo e altro! – Will

3

genera un evento dalla classe a cui il modulo può iscriversi.

1

Basta rimuovere il modificatore statico, non è necessario per i propri scopi. Ulteriori informazioni sulla statica here.

4

La sua possibile passare in un riferimento alla forma attuale in questo modo:

public static void ReceiveMSG(string message, MainForm mainform) 
{ 
    mainform.txtDisplayMessages.AppendText(message); 
} 

Anche se, come ha suggerito un evento è probabilmente un modo migliore di farlo.

+0

Questo non funziona per me. Ho inserito 'ReceiveMSG' all'interno di una classe diversa e anche se' Mainform Mainform' è dichiarato come parametro, non posso accedere ai suoi controlli. – ellekaie

1

È possibile risolvere questo problema rimuovendo la parola chiave statica.

Quando vedi "statico", pensa: senza un'istanza di questo tipo.

Quando si chiama un metodo non statico, è necessario utilizzare esplicitamente qualche istanza. Il metodo può accedere a quell'istanza usando la parola chiave "this".

Quando si chiama un metodo statico, non esiste un'istanza: si sono abbandonati i limiti di OO e si trovano ora in un contesto di programmazione strutturale o funzionale. Se vuoi un'istanza di qualcosa, devi portarla come parametro.

1

Penso che potresti avere l'approccio sbagliato su questo. Sembra che tu stia cercando di inviare messaggi a un client da un processo esterno. Ci sono modi per farlo, ma diventerà complicato. Il mio suggerimento sarebbe quello di chiedere al cliente di sondare periodicamente qualsiasi processo con i dati, forse ogni 10 secondi a seconda delle esigenze. Questo sarà molto più facile che spingere da un server all'altro.

+0

Jonathan - perché il polling sarebbe peggio se usasse il servizio di remoting? Per quanto riguarda il threading, non sono sicuro di quale approccio si stia suggerendo, ma la maggior parte dei suggerimenti sottostanti sembrano coinvolgere eventi: se si utilizzano gli eventi, si avranno gli stessi problemi di threading. Dal momento che ha detto che è un principiante, sto solo suggerendo l'approccio più semplice che funzionerà - schiaffo un timer lì e controllare i nuovi messaggi ogni x secondi. Se hai intenzione di aggiornare ui, chiama invoke - dovrai fare la stessa cosa se segui il percorso dell'evento. – Rob

+0

-Um, no, un timer funziona su un thread diverso. - Si presume che l'origine dati sulla stessa macchina, l'autore non l'ha mai definita. Ha semplicemente detto che la fonte era "messaggi di dati in arrivo da una rete" - questo potrebbe essere un sacco di cose diverse, ma implica che, per lo meno, la fonte non è nella stessa appdomain. Ora, dato che l'autore ha un'esperienza limitata e che sta trattando con la comunicazione di più processi, pensi che capirà come consumare eventi remoti? Solo provare a buttare fuori un'opzione a cui forse non avrebbe pensato sarebbe stato facile. – Rob

+0

Sono stato corretto, ho ritirato i miei altri commenti. Ho fatto l'ipotesi che il suo codice di rete sarebbe nello stesso AppDomain. In ogni caso: : "Questo timer di Windows è progettato per un ambiente a thread singolo [...]" La sua interfaccia utente bloccherà. È ancora più facile testare . –

5

Per continuare come è stato fatto, il "TheIncomingDataClass" deve avere un riferimento all'oggetto MainForm con cui deve essere interfacciato. Quando si crea un'istanza di questa classe (presumibilmente da un metodo di istanza di MainForm), sarà necessario passare un riferimento a questo oggetto MainForm.

class TheIncomingDataClass{ 
    MainForm form; 

    public TheIncomingDataClass(MainForm form){ 
     this.form = form; 
    } 
} 

class MainForm : Form{ 
    MainForm(){ 
     new TheIncomingDataClass(this); 
    } 
} 

Tuttavia, come suggerito da Bugs, probabilmente sarebbe meglio fare questo un evento su TheIncomingDataClass e la sottoscrizione di essa da MainForm.

class IncomingMessageEventArgs : EventArgs{ 
    IncomingMessageType message; 

    public IncomingMessageType Message{get{return message;}} 

    public IncomingMessageEventArgs(IncomingMessageType message){ 
     this.message = message; 
    } 
} 

class TheIncomingDataClass{ 
    public event EventHandler<IncomingMessageEventArgs> MessageReceived; 

    protected virtual void OnMessageReceived(IncomingMessageEventArgs e){ 
     if(MessageReceived != null) 
      MessageReceived(this, e); 
    } 

    public void IncomingMessage(IncomingMessageType message){ 
     OnMessageReceived(new IncomingMessageEventArgs(message)); 
    } 
} 

class MainForm : Form{ 
    MainForm(){ 
     new TheIncomingDataClass().MessageReceived += 
      (s, e)=>txtDisplayMessages.AppendText(e.Message.ToString()); 
    } 
} 
+0

Sto provando ad usare il tuo metodo e tutto va bene tranne l'ultima parte nel MainForm. "(s, e) => txtDisplayMessages.AppendText (e.Message.ToString());" Questa riga di codice restituisce molti errori di compilazione. Specificamente la parte (s, e). – timmyg

1

Ok, ecco qui. I metodi statici possono accedere solo ai membri statici. Il tuo metodo ReceiveMSG è statico. txtDisplayMessages non lo è e quindi non puoi accedervi. Perché il tuo metodo deve essere statico? Inutile dire che se rimuovi la parola chiave statica che risolverà il tuo problema.

Basta rendere ReceiveMSG parte di una classe, creare un'istanza della classe e quindi chiamare il metodo sull'istanza.

Penso che dovresti pubblicare il tipo di soluzione che ti aspetti.

0

Visto che siete nuovi in ​​C# manterrò il più semplice possibile. Dovresti avere un file Program.cs che abbia un singolo metodo Main (questo sarebbe stato generato da Visual Studio). Sarà necessario far sembrare il seguente:

class Program 
{ 
    public static readonly MainForm MainForm; 

    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     MainForm = new MainForm(); // These two lines 
     Application.Run(MainForm); // are the important ones. 
    } 
} 

Ora nel tuo messaggio in arrivo si avrà un modo per accedere a quella forma.

public void IncomingMessage(IncomingMessageType message) 
{ 
     Program.MainForm.RecieveMSG(message); 
} 

Tale metodo nella forma sarebbe quindi un metodo di istanza (non statico). Per esempio.

public void RecieveMSG(IncomingMessageType message) // NB: No static 
{ 
    txtDisplayMessages.Text = message.Text; // Or whatever. 
} 

Ci sono modi migliori per farlo - ma come principiante penso che questo sarebbe l'approccio migliore.

La differenza tra statico e istanza (l'istanza è quando non si dice statico) è enorme. Per ottenere un metodo, un campo o una proprietà di istanza (che sono chiamati collettivamente membri in C#) è necessario avere l'istanza contenente. Quindi:

Person p = new Person(); // You now have an instance. 
p.Name = "Fred"; // You are using an instance property. 

statiche sono l'opposto, sono la stessa ovunque nella vostra applicazione (più tecnicamente all'interno dello stesso dominio di applicazione - ma se sei un principiante non sarà necessario preoccuparsi di che per un po '). Non hai bisogno di un'istanza per raggiungerli (oggetti per i codewidgets "I metodi statici possono accedere solo ai membri statici"). Ad esempio:

// Where Planet is a class and People is a static property. 
// Somewhat confusingly the Add method is an instance - best left for the student :). 
Planet.People.Add(new Person("Fred")); 

Speriamo che questo dia una buona indicazione di cosa sia l'istanza e l'istanza e dove usarli. La cosa più importante però è cercare di evitare membri statici nel miglior modo possibile: possono causare incubi di manutenzione.

Microsoft ha un intero write-up sui concetti importanti in relazione a questo.

+0

In che modo avere un membro statico crea un incubo di manutenzione? – Rob

+0

Rende più difficile il refactoring. Più volte mi sono scavato in un buco con esso - soprattutto in termini di threading. È meglio imparare a lavorare senza troppi membri statici nella fase iniziale. –

+0

Immagino che potresti creare un incubo per te stesso se non capisci OOD o come scrivere codice gestibile, ma sarebbe colpa degli sviluppatori. Per quanto riguarda il threading, gli sviluppatori devono solo capire come scrivere codice thread-safe. .Net ha un sacco di buone classi per aiutare con questo. I membri statici hanno il loro posto e la loro comprensione è fondamentale per alcuni modelli di progettazione software molto importanti. Non direi mai a nessuno di stare lontano da loro. – Rob

Problemi correlati