Search code examples
c#wpfprogram-entry-point

Get reference to MainWindow in custom main() in WPF


I am trying to write a custom Main() function for my WPF app so I can parse the command line and configure the GUI based on the command line. I can't figure out how to get a reference to the MainWindow instance created by the default implementation of Main(). The auto-generated implementation found in App.g.cs is below:

public void InitializeComponent() {
    if (_contentLoaded) {
        return;
    }
    _contentLoaded = true;

    #line 5 "..\..\..\App.xaml"
    this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative);

    #line default
    #line hidden
    System.Uri resourceLocater = new System.Uri("/MyApplication;component/app.xaml", System.UriKind.Relative);

    #line 1 "..\..\..\App.xaml"
    System.Windows.Application.LoadComponent(this, resourceLocater);

    #line default
    #line hidden
}

[System.STAThreadAttribute()]
public static void Main() {
    MyApplication.App app = new MyApplication.App();
    app.InitializeComponent();
    app.Run();
}

The problem I'm running into is trying to get a reference to my MainWindow class after it is instantiated (however that is actually done via StartupUri). I'd expect to be able to do something like:

[System.STAThreadAttribute()]
public static void Main() {
    MyApplication.App app = new MyApplication.App();
    app.InitializeComponent();
    MyApplication.MainWindow w = (MyApplication.MainWindow)app.MainWindow;
    w.MyProgramIsAwesomeProperty = true;
    app.Run();
}

But, the app.MainWindow is always null. I've also tried the following and setting breakpoints on the Console.WriteLine lines, but the program never reaches those callbacks:

[System.STAThreadAttribute()]
public static void Main() {
    MyApplication.App app = new MyApplication.App();
    app.LoadCompleted += app_LoadCompleted;
    app.Activated += app_Activated;
    app.InitializeComponent();
    app.Run();
}

static void app_Activated(object sender, EventArgs e)
{
    Console.WriteLine("Activated");
}

static void app_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    Console.WriteLine("LoadCompleted");
}

So, how can I get a reference to MyApplication.MainWindow after it's been instantiated in my Main function?


Solution

  • If you want to send something from the command line to the GUI, you're better off calling a method in your Application class and opening your GUI from that.

    Open your App.xaml file, remove the StartupUri attribute from the Application element, and add a Startup attribute:

    Startup="Application_Startup"
    

    Then create an Application_Startup method in your Application class that reads the command line or whatever and sends that to your GUI:

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // e.Args contains command-line arguments.
        MainWindow mw = new MainWindow(Whatever(e.Args));
        mw.Show();
    }