C# 在WPF中共享应用程序资源
从中,我读到: 如果应用程序使用自定义控件并在ResourceDictionary(或XAML resources节点)中定义资源,建议您在应用程序或窗口对象级别定义资源,或在自定义控件的默认主题中定义资源。在自定义控件的ResourceDictionary中定义资源会对该控件的每个实例施加性能影响 好的。。。现在,我有一个UserControl,它定义了以下资源:C# 在WPF中共享应用程序资源,c#,wpf,nested-resources,C#,Wpf,Nested Resources,从中,我读到: 如果应用程序使用自定义控件并在ResourceDictionary(或XAML resources节点)中定义资源,建议您在应用程序或窗口对象级别定义资源,或在自定义控件的默认主题中定义资源。在自定义控件的ResourceDictionary中定义资源会对该控件的每个实例施加性能影响 好的。。。现在,我有一个UserControl,它定义了以下资源: <UserControl ...> <UserControl.Resources>
<UserControl ...>
<UserControl.Resources>
<Namespace:ImagesConverter x:Key="ImagesConverter" ...
<Storyboard x:Key="AnimationHide" ...
</UserControl.Resources>
我应该如何修改它以反映这些更改?我应该如何修改下面的UserControl XAML代码段
Source="{Binding Source={x:Static Properties:Resources.MyImage}, Converter={StaticResource ImagesConverter}}"
就我个人而言,我更喜欢使用
App.xaml
或单独使用ResourceDictionary
,而不是将它们全部添加到窗口中。Resources
,这样可以消除窗口中的混乱
这还允许您轻松地为应用程序创建主题
,因为它们都位于一个位置,因此您可以复制现有的资源字典
更改笔刷颜色等,您可以选择要加载的资源字典
,并轻松地更改应用程序的整个外观
至于访问Usercontrol
中的resources
在xaml端没有区别,您将继续使用{StaticResource resourceKey}
,就像调用StaticResource
时,它搜索资源
层次结构以查找资源
因此,如果将资源从UserControl.Resources
移动到Window.Resources
或Application.Resources
,则无需更改通过{StaticResource resourceKey}
访问的xaml代码中的任何内容
至于代码隐藏中的访问,您将使用FindResource(“resourceKey”)
而不是Resources[“resourceKey”]
,因为FindResource
将像xaml中的StaticResource
一样在层次结构中搜索资源
例如:
m_AnimationHide = (Storyboard)FindResource("AnimationHide");
如果要修改特定控件中的任何资源,并且这些资源已冻结,则只需为该实例创建一个副本即可
范例
var animation = FindResource("AnimationHide") as Storyboard;
m_AnimationHide = animation.Clone();
m_AnimationHide.Completed += m_AnimationHide_Completed;
您还可以设置x:Shared=“false”
这将每次从资源返回一个新的动画实例,如果您有一个复杂的资源需要更改其中的值,这将在整个应用程序中保存复制/粘贴相同的动画
<Storyboard x:Key="AnimationHide" x:Shared="false" />
然后您就可以在本地修改资源了。我想详细介绍一下将资源移出控制xaml的原因
正如您在MSDN库中所读到的,将任何内容提升到更高级别的唯一技术原因是为了节约资源(即内存)。ResourceDictionary中的每个条目在运行时创建为对象(=实例!),占用内存,初始化需要几个CPU周期
现在,像故事板这样的捕获:必须为它应该驱动的控件的每个实例创建一个对象,该对象存储与控件的特定实例(如正在执行的动画实例)相关甚至连接的数据。除非希望所有控件都以相同的方式并行设置动画
对我来说,在代码中使用Clone
,而不是一开始就把它放到xaml中,没有多大意义。xaml方法需要一点复制/粘贴,因此意味着在多个位置修改动画(如果您甚至可以跨控件重复使用类似的内容)但是它将删除代码要求,并且仍然执行相同的操作:为控件的每个实例创建一个情节提要的实例。我按照您所说的做了,但出现了一些问题。我的UserControl中有一段代码如下:animation.Completed+=handler代码>。每当我到达那里。我的应用程序崩溃,告诉我:DoubleAnimation必须将isfreeze设置为false才能修改
。这些动画必须在完成时触发它们的UserControl上执行某些操作。如何修复它?因为您不能将静态资源修改为冻结资源,所以我在回答中添加了一个解决方法谢谢!我尝试了第一种方法(全部进入应用程序),效果很好。现在我正在尝试第二个(全部进入主窗口)。。。但每当我尝试将MainWindow资源引用到自定义UserControl中时,就会出现未解决的资源错误。为什么?因为不能保证用户控件
将被放置在该窗口
中,并且可以访问其资源
,所以您将使用{staticResourceKey}
而不是{dynamicResourceKey}
。这将在运行时解决。资源的层次结构是:本地对象->可视化树,直到根(承载控件的窗口)->应用程序资源。因此,如果将控件放在主窗口中,它应该可以工作。如果控件托管在另一个窗口中,将找不到资源。克隆或使用x:Shared
(克隆的xaml版本)是有意义的,因为如果您有一个主题化的应用程序,您将如何在多个位置轻松复制/粘贴资源。使用xaml或代码克隆,您只需更改主题录音带中的资源,而不必考虑整个应用程序。
<Storyboard x:Key="AnimationHide" x:Shared="false" />