5
votes

During development of my UWP app I have noticed and intersting oddity which I have hard time explaining.

I user MvvmLight and I decided to add the ViewModelLocator resource instance in a separate ResourceDictionary Core.xaml which will be referenced from MergedDictionaries in App.xaml. Following is the content of App.xaml:

<Application ...>
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/Core.xaml" />
            <ResourceDictionary Source="Resources/Converters.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
</Application>

Contents of Core.xaml:

<ResourceDictionary ...>
    <viewModel:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>

Now I supposed the resources in Core.xaml are initialized during the InitializeComponent method call in App.xaml.cs, but when I tried to use the ServiceLocator class (which is set in the constructor of ViewModelLocator in MvvmLight) - like this - ServiceLocator.Current.GetInstance<INavigationService>().Navigate<MainViewModel>(); - I get an exception saying:

An exception of type 'System.InvalidOperationException' occurred in
Microsoft.Practices.ServiceLocation.dll but was not handled in user code

Additional information: ServiceLocationProvider must be set.

Indeed, if I put an breakpoint in the constructor of ViewModelLocator, it is not called before the Window is activated. More interestingly still - if I manually reference the Locator resource key (for example putting Debug.WriteLine(Resources["Locator"]); above the call of ServiceLocator), everything works fine. The same goes if I move the ViewModelLocator resource directly to App.xaml - then it is instantiated during IntializeComponent.

Is there a lazy instantiation of merged resource dictionaries in UWP apps? Or why does it behave this way?

1
I noticed that this strange behavior occurs when you have several normal (not styles) objects in your ResourceDictionary. Having just one ViewModelLocator completely works and ctor is being called. My findings stackoverflow.com/questions/34466035/… - Alex Sorokoletov

1 Answers

6
votes

A ResourceDictionary in UWP doesn't have any code behind (no InitializeComponent). Therefore, any class references defined in a ResourceDictionary won't be initialized directly.

Neither does the App.InitializeComponent do this for you. Resource dictionaries in UWP just don't provide this functionallity - don't ask me why.

You can easily try this by trying to initialize a DataTemplate in a ResourceDictionary.
This should - sadly - neither work.

However, using the Resources["Locator"] access in code behind triggers the constructor of the class and you're fine.

This ain't be a solution, but a explanation of your problem. I hope it helps you.