开发者

How to pass a ResourceDictionary to ViewModelLocator

开发者 https://www.devze.com 2023-01-28 02:23 出处:网络
Hi i created a property in ViewModelLocator to allow a ResourceDictionary to pass to the ViewModelLocator. In my app.xaml i have this defined:

Hi i created a property in ViewModelLocator to allow a ResourceDictionary to pass to the ViewModelLocator. In my app.xaml i have this defined:

<vm:ViewModelLocator x:Key="Locator">
  <vm:ViewModelLocator.DefaultUIResourceDictionary>
    <ResourceDictionary Source="Resources/DefaultUIResource.xaml"/>
  </vm:ViewModelLocator.DefaultUIResourceDictionary>
</vm:ViewModelLocator>

It runs fine, however, when i try t开发者_开发百科o reference the dictionary, it has 0 items in it, which i'm sure DefaultUIResource.xaml has an item defined. Not sure what is wrong.

Another question is, the resources defined in the App.Resources property is only created when referenced? Can anyone tell me the life cycle of the App class? when is the items in the Resources property created? After the constructor?


Rather weirdly, the problem seems to be that your property gets passed the resource dictionary before it has been initialized - if you look at the dictionary's Source property in your DefaultUIResourceDictionary setter, it'll be null. But try this:

private ResourceDictionary _defaultUIResourceDictionary;

public ResourceDictionary DefaultUIResourceDictionary
{
    get { return _defaultUIResourceDictionary; }
    set
    {
        _defaultUIResourceDictionary = value;
        Debug.WriteLine(value.Count);
        Dispatcher.CurrentDispatcher.BeginInvoke((Action) delegate
        {
            Debug.WriteLine(value.Count);
            foreach (var item in value)
            {
                Debug.WriteLine(item);
            }
        },
        DispatcherPriority.Background,
        null);
    }
}

You'll find that the first Debug.WriteLine shows a count of 0 - the same behaviour you're seeing. But in the dispatcher callback, the count should now be correct, and the dictionary's contents available. (That's what I see when I try it.)

This may or may not be related to your other question, about when the resources actually get created. Resource dictionaries typically do deferred resource loading in WPF. I say "typically" because there are some situations in which they don't. (E.g., if you load a resource dictionary from an uncompiled Xaml stream.) But certainly, in the usual scenario - dictionaries in the Resources properties of App, or in UI elements in compiled Xaml - resources don't get loaded until you ask for them.

This is not really anything to do with the App class lifecycle. It's not the application that does the deferred loading, it's the resource dictionary itself. And it's done on a per-resource basis - individual resources get loaded the first time you look them up. This means that resources can in theory be loaded at any point in the application lifecycle. Indeed, it's common for some resources never to be loaded.

This speeds up startup for WPF apps - if all your resources got loaded at the start, it'd take much longer than necessary. Imagine you have resources only used during error conditions, for example - you don't want to make the user wait for those to load before they can start using your app.

So resource dictionaries sometimes behave a little strangely in compiled Xaml. And the behaviour you've uncovered here is definitely strange. I'm not sure it's actually meant to be like this - it may just be some unintended consequence of the fact that resource dictionaries are handled as a special case in order to enable deferred loading.


ok i found a solution:

i created another ResourceDictionary and defined inside it as follows:

<ResourceDictionary x:Key="Default" Source="/Resources/DefaultUIResource.xaml"/>

<vm:ViewModelLocator x:Key="Locator" DefaultUIResourceDictionary="{StaticResource Default}"/>

then in the App.Resources i just use ResourceDictionary's MergedDictionaries to link to this new ResourceDictionary.

0

精彩评论

暂无评论...
验证码 换一张
取 消