如何将 ResourceDictionary 传递给 ViewModelLocator

发布于 2024-10-05 07:02:39 字数 574 浏览 4 评论 0原文

您好,我在 ViewModelLocator 中创建了一个属性,以允许 ResourceDictionary 传递到 ViewModelLocator。在我的 app.xaml 中,我定义了这个:

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

它运行良好,但是,当我尝试引用字典时,它有 0 个项目,我确信 DefaultUIResource.xaml 已定义一个项目。不知道出了什么问题。

另一个问题是,App.Resources属性中定义的资源只有在被引用时才会创建吗?谁能告诉我App类的生命周期? Resources 属性中的项目是何时创建的?在构造函数之后?

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 to 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-10-12 07:02:39

相当奇怪的是,问题似乎是您的属性在初始化之前就传递了资源字典 - 如果您在 DefaultUIResourceDictionary setter 中查看字典的 Source 属性,它将会为空。但试试这个:

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);
    }
}

您会发现第一个 Debug.WriteLine 显示计数为 0 - 与您看到的行为相同。但在调度程序回调中,计数现在应该是正确的,并且字典的内容可用。 (这就是我尝试时看到的内容。)

这可能与您的其他问题(有关资源实际创建时间的问题)相关,也可能无关。资源字典通常在 WPF 中执行延迟资源加载。我说“通常”是因为在某些情况下并非如此。 (例如,如果您从未编译的 Xaml 流加载资源字典。)但当然,在通常情况下 - AppResources 属性中或 UI 元素中的字典在编译的 Xaml 中 - 资源在您请求之前不会被加载。

这实际上与 App 类生命周期没有任何关系。执行延迟加载的不是应用程序,而是资源字典本身。它是在每个资源的基础上完成的 - 当您第一次查找单个资源时,它们就会被加载。这意味着理论上可以在应用程序生命周期的任何点加载资源。事实上,某些资源永远无法加载是很常见的。

这会加快 WPF 应用程序的启动速度 - 如果在开始时加载所有资源,则所需时间会比必要的时间长得多。想象一下,您的资源仅在错误情况下使用,例如,您不希望用户等待这些资源加载后才能开始使用您的应用程序。

因此,资源字典有时在编译的 Xaml 中表现得有点奇怪。你在这里发现的行为绝对很奇怪。我不确定它实际上是这样的 - 这可能只是资源字典被作为特殊情况处理以启用延迟加载这一事实的一些意想不到的结果。

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.

动次打次papapa 2024-10-12 07:02:39

好的,我找到了一个解决方案:

我创建了另一个 ResourceDictionary 并在其中定义如下:

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

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

然后在 App.Resources 中,我只使用 ResourceDictionary 的 MergedDictionaries 链接到这个新的 ResourceDictionary。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文