1

I am trying to access a button on my default created form from a different thread in the same application. However, I get the error

An object reference is required for the non-static field, method, or property 'BElite.Form1.testButton1'

where Form1 is the default form created and testButton1 is the test button that I want to change the text of from my thread.

I understand that I somehow need to get a reference to the Form1 object... but i have no idea how!

Please help.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Jason
  • 2,445
  • 3
  • 17
  • 17
  • Do you start the thread from within a method of the Form object? Show some code. – Henrik Nov 17 '10 at 08:28
  • This link may help you as the question is a little similar: https://stackoverflow.com/questions/8566/best-way-to-access-a-control-on-another-form-in-winforms – Mamta D Nov 17 '10 at 08:28

1 Answers1

0

You are referencing testButton1 like it was a static field instead of an instance field. You need to be able to access the instance of the form. You can do this like this:

public partial class Form1 : Form
{
    public static Form1 Instance { get; private set; }

    public Form1()
    {
        InitializeComponent();

        if (Instance != null)
            throw new Exception("Only one instance of Form1 is allowed");

        Instance = this;

        FormClosed += new FormClosedEventHandler(Form1_FormClosed);
    }

    void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        Instance = null;
    }

    public Button TestButton1 { get { return testButton1; } }
}

Because controls on the form are protected by default, you have to make the button accessible. You do this using the TestButton1 property.

Now you can access the textbox using BElite.Form1.Instance.TestButton1.

Two notes:

  1. This only works if you always have a single Form1, for example when Form1 is the main form of your application;

  2. Please note that accessing these controls from a different thread must be done using Control.Invoke() or Control.BeginInvoke(). See the documentation on these methods on why and how.

You can access the button using BeginInvoke() with the following sample:

Form1.Instance.BeginInvoke(new Action(() =>
{
    Form1.Instance.TestButton1.Text = "My new text";
}));

Everything in the block ({ ... }) is safe.

Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
  • This was created using the default forms designer so... i have a "public partial class Form 1" in two places... in Main Control.cs and in Main Control.Designer.cs ... does that affect anything? – Jason Nov 17 '10 at 08:41
  • Ok if I am understanding this right... the actual CREATION of the form is at public Form1() { InitializeComponent();} correct? Also... in the auto-created code it is InitializeComponent , not InitializeComponents ... does the "s" change anything? – Jason Nov 17 '10 at 08:45
  • A pastebin of the (small) main code is located here at: http://pastebin.com/FyCKKqd8 .. it's now giving me an error that the testButton is inaccessible due to protection level... the only other file in my project so far is the default file created by the forms designer – Jason Nov 17 '10 at 08:49
  • Updated the answer by adding a `TestButton1` property. – Pieter van Ginkel Nov 17 '10 at 08:53
  • This static property is not a good idea IMHO. If you forget to set it to null after the form closes, there will always be a reference to the form and GC can't collect it. – Henrik Nov 17 '10 at 09:04
  • To change the text on that TestButton1 I need to somehow use invoke since i am accessing a rich app (Windows forms) from a new thread, correct? How can I do that? – Jason Nov 17 '10 at 09:05
  • @Henrik - Updated the answer with your feedback. Is a little bit more robust now :). – Pieter van Ginkel Nov 17 '10 at 09:14
  • Pieter thank you so much for the helpful example and code! I am going to get back on it when I wake up and hopefully I won't run into any more problems. – Jason Nov 17 '10 at 10:34
  • Pieter thanks again for the help... I just had a quick question... Why exactly do we have to implicitly state "public static Form1 Instance ..." to create a reference to the instance? Why doesn't the C# windows forms automatically create a reference for us? – Jason Nov 18 '10 at 03:48
  • Because you have a special case here. Normally, you can create as many instances of a form as you'd like. Say you're creating Word, you want to be able to have 30 Word forms open for 30 different documents. However, you have a special case where you always just have one form, like Notepad. .NET doesn't provide facilities for this special case, but with the `public static Form1 Instance`, you can create your own. – Pieter van Ginkel Nov 18 '10 at 06:09