I have created an office add-in that holds an instance of a WPF Application. When the user clicks buttons on the add-in, I launch different windows by doing the following:
MyViewModel viewModel = new MyViewModel(string infoFromOffice);
MyWindow view = new MyWindow();
view.DataContext = viewModel;
wpfApp.Run(view);
In constructing view models before my call to wpfApp.Run()
I hit probelms with the current SynchronizationContext later on. The answer here explains why. Is there a better way of launching WPF windows from an office add-in?
While Arthur's answer helped point to why the problem was happening, it did not actually answer how to pass data to a view model from a host application while still having the view model constructor call be after the call to
App.Run()
. I have since found a (very simple) solution! For anyone who is interested.In App.xaml.cs:
When launching the app:
Note that the startup URI needs to be removed in App.xaml. This very simple solution allows me to pass information to my app, but at the same time does not require that the view model be constructed in a "non WPF environment" and so can make use of the Dispatcher etc.
Here is a version using application domain to open the wpf application multiple times under separate application domains and UI thread. Used this in an office addin. Each time startup is called you get a new application. Have not verified how well the threads shutdown when the wpf app is closed.
http://eprystupa.wordpress.com/2008/07/31/running-multiple-wpf-applications-in-the-same-process-using-appdomains/
public class WpfHelper {
}
I've never created an Office add-in, but I have used WPF windows in other kinds of non-WPF applications (Windows Forms, libraries to generate .XPS files from WPF visuals, etc). You could try the approach I suggested in this question.. It shows how to configure a thread so it will be able to run the WPF app. If you take a look on the generated app's code ("App.g.i.cs") of a WPF app, it seems it is started like this:
I tried launching an app from a unit test with the following code and it worked well:
EDIT
Looking at your code I believe that the statement sensible to the SynchronizationContext is the creation of the Window instance, not the creation of your ViewModel (unless your ViewModel deals with View logic and instantiates controls, something it shouldn't be doing). So you can try to move the instantiation of the Window to the thread of the App. Something like this: