4

I hope that the title and this simple example says everything.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public void UpdateLabel(string str)
    {
        label1.Text = str;
       MessageBox.Show("Hello");
    }

    private void buttonIn_Click(object sender, EventArgs e)
    {
        UpdateLabel("inside");
    }

    private void buttonOut_Click(object sender, EventArgs e)
    {
        MyClass Outside = new MyClass();
        Outside.MyMethod();
    }
}

public class MyClass
{
    public void MyMethod()
    {
         Form1 MyForm1 = new Form1();
         MyForm1.UpdateLabel("outside");
    }
}

When I'm trying to change lable1 from MyClass it does nothing. But I can get to the UpdateLable method from outside, it says Hello to me, it just doesn't change the label.

Raj
  • 22,346
  • 14
  • 99
  • 142
cozzy
  • 147
  • 1
  • 3
  • 8
  • 2
    Learn the difference between a class and an instance of the class. It's the difference between "dog" and "my dog Fido". – John Saunders Jul 23 '11 at 23:48
  • Ok I see, my code is completly wrong. So how do I change that label from class? – cozzy Jul 23 '11 at 23:54
  • You don't want to change the 'Class' keyword (I'm assuming that's what you mean by 'label'). Maybe just tell us what you're actually trying to do (more context) and we can help you. – Jason Down Jul 24 '11 at 00:08
  • Ok, I have a program that is solving something and it works for some time(less than minute). I am using a BackgroundWorker(possible thread problem?) which starts this solving program that is written in one Class. When one iteration is complete a want to report the progress to the Form in label. E.g. "Program is on: 24864 iteration, already found solutions: 3.". Sadly this is not more comprehensible I think, huh? – cozzy Jul 24 '11 at 00:34
  • If you need to update the label from a background thread, you'll need to invoke Label1. – Jason Down Jul 24 '11 at 01:13

5 Answers5

9

Use a delegate for setting your label

public class MyClass {
    Action<String> labelSetter;

    public MyClass(Action<String> labelSetter) {
        this.labelSetter = labelSetter;
    }

    public void MyMethod() {
        labelSetter("outside");
    }
}

.

public void buttonOut_Click(object sender, EventArgs e) {
    var outside = new MyClass(UpdateLabel);
    outside.MyMethod();
}
Mark H
  • 13,797
  • 4
  • 31
  • 45
3

a bit unsure because the example actually leaves some bits unclear... but here is a try:

public class MyClass
{
    public void MyMethod(Form1 F)
    {
         F.UpdateLabel("outside");
    }
}

this works as long as MyClass is NOT running on a different thread - otherwise the call to UpdataLabel must be synchronized with the UI thread...

EDIT:

private void buttonOut_Click(object sender, EventArgs e)
{
    MyClass Outside = new MyClass();
    Outside.MyMethod(this);
}
Yahia
  • 69,653
  • 9
  • 115
  • 144
  • what does NOT work ? Is there an exception/error message... ? – Yahia Jul 23 '11 at 23:56
  • No, but the label is not changing. – cozzy Jul 23 '11 at 23:58
  • `code`(private void buttonOut_Click(object sender, EventArgs e) { MyClass Outside = new MyClass(); Form1 MyForm1 = new Form1(); Outside.MyMethod(MyForm1); } } public class MyClass { public void MyMethod(Form1 F) { F.UpdateLabel("outside"); } }) – cozzy Jul 24 '11 at 00:05
3

Either go with Yahia's way (it has been updated and will work correctly) or try the following (probably overkill for what you're trying to do... whatever that is).

UPDATE:

Based on your comment in the question, you are also doing the work in MyClass on a different thread. Code change is below.

public partial class Form1 : Form
{
    // keep a reference to a MyClass object for your Form's lifetime
    private MyClass _myClass;

    public Form1()
    {
        InitializeComponent();

        // Intstantiate your MyClass object so you can use it.
        _myClass = new MyClass();

        // Register to the MyClass event called UpdateLabel.
        // Anytime MyClass raises the event, your form will respond
        // by running the UpdateLabelFromMyClass method.
        _myClass.UpdateLabel += UpdateLabelFromMyClass;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Call MyMethod in your MyClass object. It will raise
        // the UpdateLabel event.

        // update, you are calling this on a background thread?
        _myClass.MyMethod();
    }

    void UpdateLabelFromMyClass(string message)
    {
        // Update your label with whatever message is passed in
        // from the MyClass.UpdateLabel event.

        // UPDATE: If called from a background thread you'll need this:
        this.BeginInvoke( (Action) (()=>
        {
            label1.Text = message;
        }));            
    }
}

public class MyClass
{
    // An event that can be raised, allowing other classes to
    // subscribe to it and do what they like with the message.
    public event Action<string> UpdateLabel;

    public void MyMethod()
    {
        // Raise the UpdateLabel event, passing "Outside" as
        // the message.
        UpdateLabel("Outside");
    }
}
Community
  • 1
  • 1
Jason Down
  • 21,731
  • 12
  • 83
  • 117
  • It works but, it gives me a new form. The clone of the first one – cozzy Jul 24 '11 at 00:04
  • @cozzy: If you're trying to update an instance of a Form1 object that contains a reference to a MyClass object, why not try raising an event in MyClass and having Form1 respond to it? I can post a sample if you wish. – Jason Down Jul 24 '11 at 00:10
0

After wasting a ton of time on what should be a simple task and trying every answer on stack overflow, I said, if C# wants to make it stupid hard to change the text of a simple label, I am going to come up with a stupid fix.

Here is what you do:

  1. In Form1 or whatever form has the label you want add: public void setStatus() { lblStatus.Text = status; }

    public static string status;
    
  2. Now, add a timer to Form1 and have it run "setStatus();" on every tick

  3. Now, in any class, just write: Form1.status = "Change label to this text";

d3k4y
  • 11
  • 2
-1

you need to make both the method MyMethod and the label in question static. But if you do then you cannot access MyMethod through a new instance of the form instead you have to access it directly like Form1.MyMethod(). But if you do make the label the static visual studio will make it non-static one you access the label from the designer so you will have to keep making it static from form1.designer.cs. Also if you do make the label static change every line that refers to any of its properties so if it says this.label1.Text change it to label1.Text. This should give you the desired effect

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Henry
  • 41
  • 1
  • 5