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?
To answer the question you think you're asking, no, Office doesn't use WPF. Only Visual Studio uses it. WPF is definitely NOT a layer over Win32 (but it does use DirectX).
Microsoft has faith in WPF as a UI framework Net Core 3.0. This demonstrates that Microsoft still has faith in WPF as a user interface framework, and the company is still willing to invest in it by updating and integrating it with its new offerings.”
WPF draws its own controls and does not use built-in Win32 GUI components. The user interface is typically defined in XAML, an XML language. WPF even went cross-platform, in a sense, when Microsoft introduced Silverlight, cut-down WPF for embedding in web pages, and then later for Windows Phone.
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:
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static void Main() {
WpfApplication1.App app = new WpfApplication1.App();
app.InitializeComponent();
app.Run();
}
I tried launching an app from a unit test with the following code and it worked well:
[TestMethod]
public void TestMethod()
{
// The dispatcher thread
var t = new Thread(() =>
{
var app = new App();
// Corrects the error "System.IO.IOException: Assembly.GetEntryAssembly() returns null..."
App.ResourceAssembly = app.GetType().Assembly;
app.InitializeComponent();
app.Run();
});
// Configure the thread
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
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:
[TestMethod]
public void TestMethod3()
{
// Creates the viewmodel with the necessary infomation wherever
// you need to.
MyViewModel viewModel = new MyViewModel(string infoFromOffice);
// The dispatcher thread
var t = new Thread(() =>
{
var app = new App();
// Corrects the error "System.IO.IOException: Assembly.GetEntryAssembly() returns null..."
App.ResourceAssembly = app.GetType().Assembly;
app.InitializeComponent();
// Creates the Window in the App's Thread and pass the information to it
MyWindow view = new MyWindow();
view.DataContext = viewModel;
app.Run(view);
});
// Configure the thread
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With