0

I'm a bit confused during my transition from VB to c# - I have a UserForm that's started from the Main point:

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new AwesomeForm());
    }
}

On this form I've got a label, Label1, but I can't access it from another class (AwesomeForm.Label1 doesn't exist in intellisense) - it won't find Label1 or in fact any of the public methods in the form; I tried to make a method on the AwesomeForm with a public accessor:

    public void UpdateMe(string TheMessage)
    {
        this.Label1.Text = TheMessage;
    }

In VB I would simply just use the name of the form and the public method (AwesomeForm.UpdateMe("Hi!")

I gather this has got something to do with the Application.Run(new AwesomeForm()); creating an instance of AwesomeForm and I thought I may be able to access the instance with public Form MyAwesomeForm = Application.OpenForms[0]; giving me MyAwesomeForm to play with, but while that line doesn't error, I still don't get a list of methods in intellisense and it doesn't compile when I try to use Form.UpdateMe()

I tried declaring a variable for it, public AwesomeForm MyAwesomeForm = Application.OpenForms[0]; but that didn't work...

Where am I going wrong?! How can I tell a class somewhere else to change something in the start-up form?

Can I just put a variable name somewhere in the line Application.Run(new AwesomeForm()); e.g. Application.Run(Wow new AwesomeForm()); and then I can get the first instance of an AwesomeForm?

jamheadart
  • 5,047
  • 4
  • 32
  • 63
  • 2
    C# forces you to get object-oriented programming right, no shortcuts like vb.net provides. So, for one, you *must* use a cast where one is needed, the statement can only compile with you use `(AwesomeForm)Application.OpenForms[0]`. The brain transplant is going to hurt for a while, but these restrictions might also pave the path to writing better code. Strong coupling between classes is something that always needs to be avoided. Raising an event, one that AwesomeForm subscribes, is a standard technique. A dependency injection framework is a good way to tackle complicated object models. – Hans Passant May 02 '18 at 13:25
  • I will read up on Casting, it seems to pop up all the time. One thing I find in c# as I learn more is there's less confusion... *once* you get past those shortcuts going missing vs. VB.Net - VB seems easier but it's very easy for it to mix things up. I'm coming from VBA in Excel too so I think I've got even more bad habits thinking in those slightly odd module / class / userform terms. – jamheadart May 02 '18 at 13:27

2 Answers2

1

From a combo of understanding Hans' comment and trying casiosmu's method I ended up running it as usual from the Application.Run() line and casting it in a different, static class:

public static AwesomeForm MAIN_FORM = (AwesomeForm)Application.OpenForms[0];

jamheadart
  • 5,047
  • 4
  • 32
  • 63
  • It is risky code, it hopes that the form object was already created before the static constructor runs. Exactly when it runs is unknowable, the exception you'll get is excessively ugly to debug. There is a much more oopy way to do this: https://stackoverflow.com/a/4699360/17034 – Hans Passant May 02 '18 at 15:54
0

You cannot call AwesomeForm.UpdateMe() like this because its not a static function. You either have to make it static or better create an instance of AwesomeForm and use this:

AwesomeForm f = new AwesomeForm();
f.UpdateMe("Hi");

and use it here, too

Application.Run(f);
casiosmu
  • 797
  • 1
  • 8
  • 22
  • Thanks for the reply, does that mean I could dedicate `f = new AwesomeForm();` at the start of my code and simply replace the line `Application.Run(new AwesomeForm());` ? – jamheadart May 02 '18 at 13:29
  • yes, you could use it, see my edit. But if I understand you correctly: you cannot remove the `Application.Run` because it starts the main message loop of the form, its essential. – casiosmu May 02 '18 at 13:51
  • Thats because your `F` only exists inside `Main()`. To access the AwesomeForm instance from another DebuggerForm instance, you you need to pass it there: e.g. `AwesomeForm af = new AwesomeForm(); DebuggerForm df = new DebuggerForm(af);`. Regarding the vote: if my post helps you can countervote ;-) – casiosmu May 02 '18 at 14:13
  • Maybe you should read about OOP in principle, e.g. here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/object-oriented-programming – casiosmu May 02 '18 at 14:19
  • I've cracked it using casting, since I need the userform as a starting point ran from Program.cs, I then just set it in a static class I have saved for general app definitions. – jamheadart May 02 '18 at 14:25