2009-06-04 36 views
6

Tengo una aplicación en C# .net que tiene un MainForm y algunas clases.
Una de estas clases recibe mensajes de datos entrantes de una red.
Necesito obtener el texto de este mensaje anexado en un cuadro de texto multilínea en MainForm.
Puedo enviar el mensaje a un método en MainForm haciendo que el método sea estático, pero luego el método estático no puede acceder a los controles de MainForm.En C# .net, ¿cómo se accede a un control desde un método estático?

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 
} 

El error de compilación:
Se requiere una referencia de objeto para los TheApplicationName.MainForm.txtDisplayMessages no estáticos campo, el método o propiedad' '

Cualquier ayuda es apreciada.

Todavía soy un buen principiante de C# así que sea descriptivo.

Respuesta

9

Un método estático no tiene acceso a miembros como txtDisplayMessages porque no forma parte de esa instancia. Sugiero que lea un poco sobre los conceptos de métodos estáticos y otras cosas, porque ese es un concepto bastante independiente del lenguaje. Ese método se resolvería mejor eliminando el modificador estático, ya que no necesita ser estático, parece que debería ser llamado por esa instancia particular de ese objeto.

+0

Una vez que elimino la palabra clave estática del método, ya no puedo llamarla desde la clase IncomingData. No entiendo lo que quiere decir con "llamado por esa instancia particular de ese objeto", ¿podría explicarlo más?tenga en cuenta que necesito que estos mensajes se envíen al cuadro de texto inmediatamente después de recibirlos, por lo que el evento sería la recepción de un mensaje. Gracias. – timmyg

+0

Supongo que es estático que lo estaba llamando con MainForm. ReceiveMSG() [o simplemente ReceiveMSG()]. Tendría que ser llamado desde una instancia específica de MainForm, (MainForm mf = new MainForm(), o similar, para crear una instnance). Entonces, podrías llamarlo como mf. ReceiveMSG(), reemplazando mf con lo que usted denominó su instancia de MainForm. Sin ánimo de ofender, pero creo que debes leer literatura sobre la orientación de objetos, aprender todo lo que esto significa, y luego ver cómo la sintaxis de C# se relaciona con ella. – Annath

+0

En serio, debes tomar CLR Via C#. Es una lectura fácil (PASE LA PRIMERA PAREJA DE CAPÍTULOS) y entra en detalles sobre esto y más. – Will

3

plantee un evento de la clase a la que se puede suscribir el formulario.

1

Simplemente elimine el modificador estático, no lo necesita para sus propósitos. Lea acerca de la estática here.

4

Su posible pasar de una referencia a la forma actual de esta manera:

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

Aunque como se sugiere un evento es probablemente una mejor manera de hacerlo.

+0

Esto no funciona para mí. Puse 'ReceiveMSG' dentro de una clase diferente y aunque' MainForm mainform' se declara como un parámetro, no puedo acceder a sus controles. – ellekaie

1

Puede resolver este problema eliminando la palabra clave estática.

Cuando vea "estático", piense: sin una instancia de este tipo.

Cuando llama a un método no estático, debe usar explícitamente alguna instancia. El método puede acceder a esa instancia usando la palabra clave "this".

Cuando llama a un método estático, no hay instancia: ha abandonado los límites de OO y ahora se encuentra en un contexto de programación estructural o funcional. Si desea una instancia de algo, debe incluirlo como parámetro.

1

Creo que podría estar tomando el enfoque equivocado en esto. Parece que está intentando enviar mensajes a un cliente desde un proceso externo. Hay formas de hacerlo, pero se complicará. Mi sugerencia sería que el cliente realice una encuesta de forma periódica en cualquier proceso que tenga datos, tal vez cada 10 segundos según sus necesidades. Esto va a ser muchísimo más fácil que pasar de un servidor a otro.

+0

Jonathan: ¿por qué las encuestas serían peores si utilizara la comunicación remota? En cuanto a enhebrar, no estoy seguro de qué enfoque está sugiriendo, pero la mayoría de las sugerencias a continuación parecen involucrar eventos: si usa eventos, tendrá los mismos problemas de enhebrado. Desde dijo que es un principiante, sólo estoy sugiriendo el enfoque más simple que funcione - una palmada a un temporizador de allí y comprobar si hay nuevos mensajes cada x segundos. Si va a actualizar ui, llame a invocación: tendrá que hacer lo mismo si va a la ruta del evento. – Rob

+0

-Um, no, un temporizador se ejecuta en un hilo diferente. -Suponiendo que la fuente de datos en la misma máquina, el autor nunca definió eso. Simplemente dijo que la fuente era "mensajes de datos entrantes de una red", esto podría ser un montón de cosas diferentes, pero implica que, como mínimo, la fuente no está en el mismo dominio de aplicación. Ahora, dado que el autor tiene una experiencia limitada y que está tratando con múltiples procesos, ¿cree que va a entender cómo consumir eventos remotos? Solo tratar de descartar una opción que quizás no haya pensado sería fácil de hacer. – Rob

+0

Me corrigen, me he retractado de mis otros comentarios. Supuse que su código de red estaría en el mismo Dominio de Aplicación. En cualquier caso: : "Este temporizador de Windows está diseñado para un entorno de subproceso único [...]" Su UI se bloqueará. Es incluso más fácil probar . –

5

Para continuar la forma en que lo ha estado haciendo, su "TheIncomingDataClass" debe tener una referencia al objeto MainForm con el que debe interactuar. Cuando crea una instancia de esta clase (presumiblemente desde un método de instancia de MainForm), deberá pasar una referencia a este objeto MainForm.

class TheIncomingDataClass{ 
    MainForm form; 

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

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

Sin embargo, según lo sugerido por Bugs, probablemente estaría mejor haciendo de este un evento en TheIncomingDataClass y suscribirse a él desde 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

Estoy tratando de usar su método y todo va bien, excepto la última parte en MainForm. "(s, e) => txtDisplayMessages.AppendText (e.Message.ToString());" Esta línea de código devuelve muchos errores de compilación. Específicamente la parte (s, e). – timmyg

1

Ok here goes. Los métodos estáticos solo pueden acceder a miembros estáticos. Su método ReceiveMSG es estático. txtDisplayMessages no es, y por lo tanto, no puedes acceder a él. ¿Por qué su método debe ser estático? No hace falta decir que si elimina la palabra clave estática que solucionará su problema.

Simplemente haga de ReceiveMSG parte de una clase, cree una instancia de la clase y luego llame al método en la instancia.

Creo que deberías publicar el tipo de la solución que estás esperando.

0

Dado que eres nuevo en C# Lo mantendré lo más simple posible. Debería tener un archivo Program.cs que tenga un único método Main (esto habría sido generado por Visual Studio). Tendrá que hacer que se vea como la siguiente:

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. 
    } 
} 

En su mensaje de entrada que tendrá una forma de acceder a esa forma.

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

Ese método en la forma sería entonces un método de instancia (no estático). P.ej.

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

Hay mejores formas de hacerlo, pero como principiante, creo que este sería el mejor enfoque.

La diferencia entre la estática y la instancia (instancia es cuando no se dice estático) es enorme. Para llegar a un método, campo o propiedad de instancia (que se denominan colectivamente miembros en C#), debe tener la instancia que lo contiene. Por lo tanto:

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

estático son todo lo contrario, que son los mismos en cualquier lugar de su aplicación (más técnicamente dentro del mismo dominio de aplicación - pero si usted es un principiante que no tendrá que preocuparse de que por un tiempo). No necesita una instancia para llegar a ellos (accesorios para las herramientas de código "Los métodos estáticos solo pueden acceder a los miembros estáticos"). Por ejemplo:

// 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")); 

Afortunadamente eso le da una buena indicación de qué estática e instancia es y dónde usarlas. Sin embargo, lo más importante es tratar de evitar miembros estáticos de la mejor manera posible: pueden causar pesadillas de mantenimiento.

Microsoft tiene un total write-up en los conceptos importantes con respecto a esto.

+0

¿De qué manera tener un miembro estático crea una pesadilla de mantenimiento? – Rob

+0

Hace la refactorización más difícil. Una y otra vez me he metido en un hoyo con ella, especialmente en términos de enhebrado. Lo mejor es aprender cómo trabajar sin demasiados miembros estáticos desde el principio. –

+0

Supongo que podría crear una pesadilla para usted si no entiende OOD o cómo escribir código mantenible, pero eso sería culpa de los desarrolladores. En lo que respecta al enhebrado, los desarrolladores solo necesitan comprender cómo escribir código seguro para subprocesos. .Net tiene muchas clases agradables para ayudar con esto. Los miembros estáticos tienen su lugar y entenderlos es fundamental para algunos patrones de diseño de software muy importantes. Nunca le diría a nadie que se mantenga alejado de ellos. – Rob

Cuestiones relacionadas