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

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube