I have a simple MVVM application. Some ViewModels perform asynchronous processing, which require notifying the View about status updates and when the processing finished.
Since direct calls to View are restricted in MVVM, I chose Commands. Unfortunately, the commands do not get executed when called from continuation tasks even though the tasks are synchronized to the main (UI) thread:
public void DoAction()
{
//NOTE: command gets executed correctly
AppCommands.SomeCommand.Execute(null, null);
// run some task asynchronously
Task task = new Task( ... );
task.ContinueWith(
taskAntecedent =>
{
//NOTE: command does not get executed at all!
AppCommands.SomeCommand.Execute(null, null);
},
TaskScheduler.FromCurrentSynchronizationContext());
task.Start();
}
The coomand gets always executed if the Execute method contains proper target element (so that WPF can walk up the visual tree and find the command binding). But this cannot be done in ViewModel as it should not see the View.
Some other solutions I tried use:
Dependency injection - injecting View to ViewModel via constructor as some interface. Doable, but this creates a room for errors: 1. the ViewModel cannot be used in XAML as ViewModel no longer has an empty contructor. 2. even if I define an empty contructor, the develper may forget to use proper one and inject proper View in it (some Views have several possible ViewModels that can be replaced by the user).
Routed Events - the ViewModel should be replaceable and this means the View has to unhook events from old model and rehook to the new model which requires code-behing in the View (not MVVM-like)
Services - some Views are UserControls and unlike Windows, they don't have Loaded, Unloaded events - so there is no good place to register and unregister the service. Also multiple controls can be created, thus registering the same service multiple times, then the binding between Views and ViewModels would no loger be 1:1.
The problem is simple:
How to e.g. close window from UserControl's ViewModel without lots of extra coding on the View side or by the user/developer?
I want to do this in vanilla WPF, not use a 3rd party MVVM framework as the application should be lightweight/easy-to-understand (with as little black magic as possible).