在 WPF 的自定义 main() 中获取对 MainWindow 的引用

Get reference to MainWindow in custom main() in WPF

我正在尝试为我的 WPF 应用程序编写自定义 Main() 函数,以便我可以解析命令行并基于命令行配置 GUI。我不知道如何获取对 Main() 默认实现创建的 MainWindow 实例的引用。 App.g.cs 中自动生成的实现如下:

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();
}

我 运行 遇到的问题是在 MainWindow class 实例化后试图获取对它的引用(但实际上是通过 StartupUri ).我希望能够做类似的事情:

[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();
}

但是,app.MainWindow 总是 null。我还尝试了以下并在 Console.WriteLine 行上设置断点,但程序从未到达这些回调:

[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");
}

那么,在我的 Main 函数中实例化后,如何获取对 MyApplication.MainWindow 的引用?

如果您想从命令行向 GUI 发送内容,最好在您的应用程序中调用一个方法 class 并从中打开您的 GUI。

打开 App.xaml 文件,从 Application 元素中删除 StartupUri 属性,然后添加 Startup 属性:

Startup="Application_Startup"

然后在您的 Application class 中创建一个 Application_Startup 方法来读取命令行或其他任何内容并将其发送到您的 GUI:

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

实际上,设置StartupUri并没有实例化mainwindow,也没有设置对应的Application.MainWindow属性。这会在稍后发生,在调用 Run 方法之后,这就是您得到 null 的原因。

正确的方法是避免使用 StartupUri 并覆盖 OnStartup 方法(虽然您可以按照建议添加事件处理程序,但在派生 class 中没有多大意义).然后,在OnStartup中,你可以直接实例化main window,然后设置你要设置的属性。