Code Focused

Magic Forms Access in Visual Basic and C#

Look behind the curtain on this one, and you'll see that code is quite magical in and of itself.

Accessing a specific form within a Visual Basic Windows Forms application is magical. Simply naming the form in any part of your source code causes that form to--presto--magically pop into existence:

Form2.ShowDialog()
' ----- And there it is!

Behind the scenes, Visual Basic is treating the form mention as a shortcut to the My.Forms pseudo-collection:

My.Forms.Form2.ShowDialog()

This is a little more informative, but you still can't tell what's really going on, because it's magic. If you could peer inside the My.Forms feature, you might find Visual Basic adding parallel form access points for every Form-derived class you include in your application, as shown in Listing 1.

Listing 1: My.Forms Module 
Partial Friend Module My.Forms
  ' ----- Internal, hidden storage for the magic form.
  Private InternalForm2 As WindowsApplication1.Form2 = Nothing

  ' ----- The public face of the magic form.
  Public Property Form2 As WindowsApplication1.Form2
    Get
      ' ----- Ensure a form always appears when requested.
      If (InternalForm2 Is Nothing) Then _
        InternalForm2 = New WindowsApplication1.Form2
      Return InternalForm2
    End Get
    Set(value As WindowsApplication1.Form2)
      ' ----- Allow clearing, but not overwriting, of form.
      If (value Is Nothing) Then
        InternalForm2 = Nothing
      Else
        Throw New Exception("That's a no-no.")
      End If
    End Set
  End Property
End Module

So, it's not magic, it's just code. Which means it's just like C#, because -- and learning this is part of growing up and becoming an adult -- the C# language has no magic. It also means you can do the same kind of form-magic thing in C#, if you add similar code, as shown in Listing 2.

Listing 2: My.Forms Module a la C# 
static internal partial class MyForms
{
  // ----- Internal, hidden storage for the magic form.
  private static WindowsFormsApplication1.Form2 InternalForm2 = null;

  public static WindowsFormsApplication1.Form2 Form2
  {
    get
    {
      // ----- Ensure a form always appears when requested.
      if (InternalForm2 == null)
        InternalForm2 = new WindowsFormsApplication1.Form2();
      return InternalForm2;
    }
    set
    {
      // ----- Allow clearing, but not overwriting, of form.
      if (value == null)
        InternalForm2 = null;
      else
        throw new Exception("That's a no-no.");
    }
  }
}

Now you can do the magic in C#:

MyForms.Form2.ShowDialog();

A big downside to this code is that you must add it for every form included in your project. You could inject yourself into the Roslyn code generation process and emit the necessary partial MyForms class elements on a per-Form basis. Another option would be to use Reflection to scan through your assembly at runtime, looking for valid forms, and providing access to each one through an indexer or similar construct. But those sound like a lot of work. Don't those sound like a lot of work to you?

Of course, all of this begs the question as to whether this is the best way of invoking forms in a Windows Forms application. The traditional way of creating forms in C#, via as-needed instantiation, is probably the best way to manage form lifetimes in both C# and Visual Basic:

// ----- The best C# way...
(new WindowsFormsApplication1.Form2()).ShowDialog();

' ----- And its Visual Basic equivalent...
Call (New WindowsApplication1.Form2).ShowDialog()

But that's just code, not magic. And every program needs a little magic now and then.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.

comments powered by Disqus

Featured

Subscribe on YouTube