timmyg
timmyg

Reputation: 1055

How does one access a control from a static method?

I have an application in C# .NET which has a MainForm and a few classes.

One of these classes receives incoming data messages from a network. I need to get these message's text appended into a multi-line textbox on the MainForm.

I can send the message to a method in the MainForm by making the method static, but then the static method cannot access the MainForm's controls.

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
}

The compile error:

An object reference is required for the nonstatic field, method, or property 'TheApplicationName.MainForm.txtDisplayMessages'

Upvotes: 8

Views: 43337

Answers (10)

ngthna
ngthna

Reputation: 1

private void FormMain_Load(object sender, EventArgs e)
{
    TheIncomingDataClass.SetupControl(textBox1);
}

public class TheIncomingDataClass
{
    public static TextBox textbox = new TextBox();
    public static void SetupControl(TextBox txt)
    {
        textbox = txt;
    }
    public void IncomingMessage(string message)
    {
        textbox.Text = message;
    }
}

Upvotes: 0

Jonathan C Dickinson
Jonathan C Dickinson

Reputation: 7285

Seeing as you are new to C# I will keep this as simple as possible. You should have a Program.cs file that has a single method Main (this would have been generated by Visual Studio). You will need to make it look like the following:

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

Now in your incoming message you will have a way to access that form.

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

That method in the form would then be a instance (not static) method. E.g.

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

There are better ways to do it - but as a beginner I think this would be the best approach.

The difference between static and instance (instance is when you don't say static) is huge. To get to an instance method, field or property (which are collectively called members in C#) you need to have the containing instance. So:

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

Static are the opposite, they are the same anywhere in your application (more technically within the same AppDomain - but if you are a beginner you won't need to worry about that for a while). You don't need an instance to get to them (props to codewidgets "Static methods can access only static members"). For example:

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

Hopefully that gives you a good indication of what static and instance is and where to use them. The most important thing though is to try and avoid static members as best as you can - they can cause maintenance nightmares.

Microsoft has a whole write-up on the important concepts in regard to this.

Upvotes: 1

bobbyalex
bobbyalex

Reputation: 2751

Ok here goes. Static methods can access only static members. Your ReceiveMSG method is static. txtDisplayMessages is not and hence you cant access it. Why does your method need to be static? Needless to say, if you remove the static keyword that will fix your problem.

Just make ReceiveMSG part of a class, create an instance of the class and then call the method on the instance.

I think you should post the kind the solution you are expecting.

Upvotes: 1

P Daddy
P Daddy

Reputation: 29527

To continue the way you've been doing it, your "TheIncomingDataClass" should have a reference to the MainForm object with which it should interface. When you create an instance of this class (presumably from an instance method of MainForm), you will need to pass in a reference to this MainForm object.

class TheIncomingDataClass{
    MainForm form;

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

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

However, as suggested by Bugs, you probably would be better off making this an event on TheIncomingDataClass and subscribing to it from 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());
    }
}

Upvotes: 8

Peter C
Peter C

Reputation: 2287

Its possible to pass in a reference to the current form like this:

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

Although as suggested an event is probably a better way of doing it.

Upvotes: 4

Rob
Rob

Reputation: 3066

I think you might be taking the wrong approach on this. It sounds like you are trying to push messages to a client from an external process. There are ways to do this, but it will get complicated. My suggestion would be to have the client poll whatever process has the data periodically - maybe every 10 seconds depending on your needs. This is going to be a heck of a lot easier than pushing from server to client.

Upvotes: 1

Amy B
Amy B

Reputation: 110111

You can solve this problem by removing the static keyword.

When you see "static", think: without an instance of this type.

When you call a non-static method, you must explicitly use some instance. The method can access that instance using the "this" keyword.

When you call a static method, there is no instance - you have abandoned the boundaries of OO and are now in a structural or functional programming context. If you want an instance of something, you need to bring it in as a parameter.

Upvotes: 1

Annath
Annath

Reputation: 1262

A static method doesn't have access to members like txtDisplayMessages because it is not a part of that instance. I suggest you do some reading on the concepts of static methods and whatnot, because that is a fairly language agnostic concept. That method would best be served by removing the static modifier, because it doesn't need to be static - it appears that it would need to be called by that particular instance of that object.

Upvotes: 10

Bob
Bob

Reputation: 99724

Just remove the static modifier, you don't need it for your purposes. Read about statics here.

Upvotes: 1

Bugs
Bugs

Reputation: 39

raise an event from class which the form can subscribe to.

Upvotes: 3

Related Questions