Reputation: 123
I have an MVVM Light infrastructure which is all contained within a Portable Class Library targeting .Net 4, SL5, Win 8, WP 8.1, WPSL 8, Xamarin.Android and Xamarin.iOS. This works perfectly with a WPF client, however, when I try and use it in a Windows Store App/Win 8 environment I am coming up against some resistance. The first issue is found in App.xaml:
<Application
x:Class="Win8Client.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:INPS.Vision.Appointments.Shared.ViewModels"
xmlns:local="using:Win8Client">
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>
</Application>
At design time I get "Could not load file or assembly 'Microsoft.Threading.Tasks', version=1.0.12.0 ..." which is referring to my ViewModelLocator. This compiles and appears to run ok but I don't get any design time data. The design time data works fine in the WPF client.
Once running I see my first view but once this line gets called:
Slots = await _appointmentsDataProvider.GetAppointments(SelectedDate);
I get the following exception in the setter of my slots property which takes advantage of MVVM Lights Set method of ViewModelBase. The Slots property is NOT bound to any UI yet.
Exception:
"The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"
Slots Property:
public List<Slot> Slots
{
get { return _slots; }
set
{
Set(SlotsPropertyName, ref _slots, value); // <-- Exception thrown here
}
}
Realised I haven't actually asked a question. Simply, I would like to know, what is the best approach for using MVVM Light with a Windows Store App?
Thanks in advance for any help or advice!
Upvotes: 0
Views: 282
Reputation: 123
The first issue "Could not load file or assembly 'Microsoft.Threading.Tasks', version=1.0.12.0 ..." I haven't worked out yet but from time to time I do see the design data. Seems very temperamental...
The second issue - The reason this through me a bit was because is "just worked" in WPF and I assumed it would just work in a Windows Store App. Wrong. It looks like Windows Store Apps handle async/await threading differently - that's my guess.
Fix: Created an IDispatcherHelper interface in PCL with a single method declaration:
void RunOnUIThread(Action action);
Then created a single concrete DispatcherHelper class in each platform specific project (WPF/Windows 8.1) which implement IDispatcherHelper. Each implementation simply calls MVVM Lights:
DispatcherHelper.CheckBeginInvokeOnUI(action);
In App.xaml.cs in the WPF and Windows 8.1 I simply registered the concrete implementations with MVVM Lights SimpleIoc with the IDispatcherHelper as the handle. Within the view model I then use the platform specific implementations through the interface:
var slots = await _appointmentsDataProvider.GetAppointments(SelectedDate);
IDispatcherHelper dispatcherHelper = SimpleIoc.Default.GetInstance<IDispatcherHelper>();
dispatcherHelper.RunOnUIThread(() =>
{
Slots = slots;
});
Got to love abstraction!
Upvotes: 1