It may be that I am doing this the really really hard way, but I have found that fighting with the invocation precedence/order on startup by assuming anything is futile. I really wanted any exception raised during the startup of the application to IMMEDIATELY bubble up to the outermost exception handler, but even when one was raised, my MVVM Locator object was automatically instantiating itself because it is defined as an application-level resource.
That meant that the chicken arrived before the egg but after the same egg had already broken!!!
So the solution was:
1) Remove MVVM Locator from App.xaml.
2) Create an Application_Startup event
Add these lines at the top:
#region Handlers For Unhandled Exceptions
// anything else to do on startup can go here and will fire after the base startup event of the application
// First make sure anything after this is handled
// Creates an instance of the class holding delegate methods that will handle unhandled exceptions.
CustomExceptionHandler eh = new CustomExceptionHandler();
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(eh.OnAppDomainException);
// this ensures that any unhandled exceptions bubble up to a messagebox at least
Dispatcher.CurrentDispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(eh.OnDispatcherUnhandledException);
#endregion Handlers For Unhandled Exceptions
3) Tie Startup to the Application_Startup event in App.xaml
e.g.
Startup="Application_Startup" <<<< this name is arbitrary but conventional AFAICT
4) In Applicaton_Startup, create the ViewModelLocator like this:
Resources.Add("Locator", new ViewModelLocator());
//You can use FindResource and an exception will be thrown straightaway as I recall
if (!(TryFindResource("Locator") == null))
throw new ResourceReferenceKeyNotFoundException("ViewModelLocator could not be created", "Locator");
5) Then, immediately after the resource has been found, open the MainWindow, but only if the Locator was successfully instantiated
Uri uri = new Uri("pack:Views/MainWindow.xaml", UriKind.RelativeOrAbsolute);
Application.Current.StartupUri = uri;
Step (4) will throw an exception immediately if the constructor on the Locator fails WHICH HAPPENS ALL THE TIME TO ME, REGRETTTABLY.
Then, the exception from step 4 is handled as follows (this example uses a RadMessageBox but feel free to fix that:
public void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
try
{
var result = this.ShowExceptionDialog(e.Exception);
}
catch
{
RadMessageBox.Show("Fatal Dispatcher Error - the application will now halt.", Properties.Resources.CaptionSysErrMsgDlg,
MessageBoxButton.OK, MessageBoxImage.Stop, true);
}
finally
{
e.Handled = true;
// TERMINATE WITH AN ERROR CODE -1!
//Environment.Exit(-1);
}
}