fuglede
fuglede

Reputation: 18201

When running WPF app from console app, App.xaml is ignored

Suppose I've created a WPF application, let's call it TestApplication, using the default template in Visual Studio 2019, i.e. I'm set up with an App.xaml, App.xaml.cs, MainWindow.xaml, and MainWindow.xaml.cs.

I'm then trying to run this WPF application programmatically from a console application in a different assembly through

[STAThread]
static void Main(string[] args)
{
    var app = new TestApplication.App();
    app.Run();
}

Now, this won't quite work on itself. The first part of this answer provides one alternative approach: If I change app.Run() to app.Run(new TestApplication.MainWindow()), then MainWindow is actually opened.

However, this looks like it should be necessary: By default, App.xaml includes in its definition of <Application /> a StartupUri="MainWindow.xaml", which would suggest that it should somehow be able to find MainWindow on its own.

More generally, App.xaml seems to be ignored entirely through this approach; in my setup, I've included a collection of ResourceDictionary in App.xaml, and they simply won't get loaded.

So, is there some way to run a WPF application programmatically that takes into account the contents of the XAML?

Edit: After playing around a bit, I realized that InitializeComponent is responsible for handling this for windows and user controls. As suggested also by this answer, changing the above code to

[STAThread]
static void Main(string[] args)
{
    var app = new TestApplication.App();
    app.InitializeComponent();
    app.Run();
}

does indeed take me one step further, but I'm then left with a

System.IO.IOException: 'Cannot locate resource 'mainwindow.xaml'.'

I could imagine this happens because the relative paths don't resolve properly when in a different assembly, but it doesn't provide much of a hint on how to solve the issue.

Upvotes: 4

Views: 910

Answers (1)

fuglede
fuglede

Reputation: 18201

It looks like it's sufficient to also manually overwrite Application.StartupUri as follows:

[STAThread]
static void Main(string[] args)
{
    var app = new TestApplication.App();
    app.InitializeComponent();
    app.StartupUri = new Uri($"pack://application:,,,/TestApplication;component/{app.StartupUri}");
    app.Run();
}

While not the most satisfying solution in the world, it does appear to do the job in that all other relative paths in App.xaml are translated as expected; in particular, if I include in App.xaml a ResourceDictionary with a Source of, say, Style.xaml, then this is picked up properly by the console application as well.

Upvotes: 2

Related Questions