Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merged ResourceDictionary initalization in UWP app

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?

like image 780
Martin Zikmund Avatar asked Dec 17 '15 11:12

Martin Zikmund


1 Answers

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.

like image 98
Herdo Avatar answered Oct 14 '22 03:10

Herdo