在 WPF 中共享应用程序资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15582230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:16:40  来源:igfitidea点击:

Sharing Application Resources in WPF

c#wpfnested-resources

提问by Tommaso Belluzzo

From this page, I read:

这个页面,我读到:

If your application uses custom controls and defines resources in a ResourceDictionary (or XAML Resources node), it is recommended that you either define the resources at the Application or Window object level, or define them in the default theme for the custom controls. Defining resources in a custom control's ResourceDictionary imposes a performance impact for every instance of that control.

如果您的应用程序使用自定义控件并在 ResourceDictionary(或 XAML 资源节点)中定义资源,建议您在应用程序或窗口对象级别定义资源,或在自定义控件的默认主题中定义它们。在自定义控件的 ResourceDictionary 中定义资源会对该控件的每个实例产生性能影响。

Ok... now, I have a UserControl that defines the following resources:

好的...现在,我有一个定义以下资源的 UserControl:

<UserControl ...>
    <UserControl.Resources>
        <Namespace:ImagesConverter x:Key="ImagesConverter" ...
        <Storyboard x:Key="AnimationHide" ...
    </UserControl.Resources>

So, because of the fact I'm creating not less than 100 instances of them at runtime, as the MSDN tutorial says, it would be better to move those resources ad MainWindow or App level. Where's the best location to move them to? MainWindow level, App level or resource file? And why?

因此,由于我在运行时创建了不少于 100 个实例,正如 MSDN 教程所说,最好将这些资源移动到 MainWindow 或 App 级别。将它们移至何处的最佳位置?MainWindow 级别、App 级别还是资源文件?为什么?

And then... how can I use them from their new location? Let's say I have this code inside my UserControl:

然后......我如何从他们的新位置使用它们?假设我的 UserControl 中有此代码:

m_AnimationHide = (Storyboard)Resources["AnimationHide"];

How should I modify it to reflect those changes? And how should I modify the following UserControl XAML snippet instead?

我应该如何修改它以反映这些变化?我应该如何修改以下 UserControl XAML 片段?

Source="{Binding Source={x:Static Properties:Resources.MyImage}, Converter={StaticResource ImagesConverter}}"

采纳答案by sa_ddam213

Personally, I prefer to use App.xamlor seperate ResourceDictionaryover adding them all to the Window.Resources, this eliminates clutter in your Windowxaml.

就个人而言,我更喜欢使用App.xaml或单独ResourceDictionary对它们全部添加到Window.Resources您的,这消除了杂乱Window的XAML。

This also allows you to easily create Themesfor you application as you have them all in one place, so you can copy your existing ResourceDictionarychange brush colors etc, the you can choose what ResourceDictionaryyou want to load and and easily change the entire apperance of your application.

这也使您可以轻松地Themes为您的应用程序创建,因为您将它们全部放在一个地方,因此您可以复制现有的ResourceDictionary更改画笔颜色等,您可以选择ResourceDictionary要加载的内容并轻松更改应用程序的整个外观。

As for accessing the Resoucesin your Usercontrolthere is no difference on the xaml side, you will continue to use {StaticResource resourceKey}as when you call a StaticResourceit searches though the Resourcehierarchy to find the Resource.

至于访问ResoucesUsercontrol的 xaml 方面没有区别,您将继续使用{StaticResource resourceKey}as 当您调用StaticResource它时,它会通过Resource层次结构搜索以找到Resource.

So if you move you resource from UserControl.Resourcesto Window.Resourcesor Application.Resourcesyou don't need to change anything in your xaml code that is accessing though {StaticResource resourceKey}.

因此,如果您将资源从UserControl.Resourcesto移动,Window.Resources或者Application.Resources您不需要更改正在访问的 xaml 代码中的任何内容{StaticResource resourceKey}

As for access in code behind you will use FindResource("resourceKey")instead of Resources["resourceKey"]as FindResourcewill search the hierarchy for the Resourcelike the StaticResourcedoes in xaml.

至于在后面的代码中访问,您将使用FindResource("resourceKey")而不是Resources["resourceKey"]asFindResource将搜索层次结构,Resource就像StaticResource在 xaml 中所做的那样。

Example:

例子:

m_AnimationHide = (Storyboard)FindResource("AnimationHide");

If you want to modify any of these Resources in a specific control and they are frozen you can just create a copy for that instance

如果您想修改特定控件中的任何这些资源并且它们被冻结,您只需为该实例创建一个副本

Example

例子

var animation = FindResource("AnimationHide") as Storyboard;

m_AnimationHide = animation.Clone();
m_AnimationHide.Completed += m_AnimationHide_Completed;

You can also set x:Shared="false"this will return a new instance of the animation each time from the Resources, this will save copy/pasting the same animation througout your application if you have a complex Resource that you need to change values in.

您还可以设置x:Shared="false"这将每次从资源中返回一个新的动画实例,如果您有一个需要更改值的复杂资源,这将节省在整个应用程序中复制/粘贴相同的动画。

<Storyboard x:Key="AnimationHide" x:Shared="false" />

Then you will be able to modify the resource locally.

然后您将能够在本地修改资源。

回答by Roman Gruber

I'd like to expand a bit on the reasoning for moving resources out of the control xaml.

我想扩展一下将资源移出控制 xaml 的推理。

Like you read in the MSDN library, the only technical reason behind moving anything to a higher level is to conserver resources (i.e. memory). Each entry in a ResourceDictionary is created as an object (=instance!) at runtime and takes up memory and the initialization takes a few CPU cycles.

就像您在 MSDN 库中读到的那样,将任何内容移至更高级别的唯一技术原因是节省资源(即内存)。ResourceDictionary 中的每个条目都在运行时创建为一个对象(=实例!)并占用内存,初始化需要几个 CPU 周期。

Now the catch with something like the StoryBoard: An object that stores data that is relevant to or even connected to a particular instance of the control - like the instance of the executing animation - has to be created for each instance of the control it should drive. Unless you want all your controls to animate identically and in parallel.

现在抓住类似 StoryBoard 的东西:必须为它应该驱动的每个控件实例创建一个对象,该对象存储与控件的特定实例相关甚至连接到特定实例的数据 - 例如正在执行的动画的实例. 除非您希望所有控件都具有相同且并行的动画效果。

To me it doesn't make much sense to use Clonein code as opposed to just put that thing into the xaml in the first place. The xaml approach takes a bit of copy/paste and thus would mean to modify the animation in more than one place (if you even canre-use something like that across controls) but it will remove the code requirement and still do the same: create an instance of the Storyboardfor each instance of the control.

对我来说,Clone在代码中使用没有多大意义,而不是首先将它放入 xaml 中。xaml 方法需要一些复制/粘贴,因此意味着在多个地方修改动画(如果您甚至可以跨控件重复使用类似的东西),但它将删除代码要求并仍然执行相同的操作:Storyboard为控件的每个实例创建一个实例。