Reputation: 18201
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
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