如何在设计时在棱镜模块中使用资源字典?
我在一个silverlight应用程序中使用prism框架,在单独的XAP中有多个模块。
我在我的shell项目中定义了一个资源字典。 在我的模块中,我可以很好地使用资源,但由于模块与shell分离,直到它们在运行时加载,设计器不会显示它们或识别它们。
有没有办法让模块在设计时知道我的资源而不在每个视图xaml中合并我的资源文件?
我的资源文件位于“常见”项目中。
我想我肯定有设计时资源的解决方案。
优点:
- 它适用于任何基于模块(MEF,UNITY ..)的应用程序。
- 它适用于任何设计师(Visual Studio,Blend ..)
- 它不会创建相同ResourceDictionary的多个实例
让我们考虑以下解决方案:
- MyApp.Shell(.exe)
- MyApp.Module1(.dll) – 在运行时使用MEF加载
- MyApp.Module2(.dll) – 使用MEF在运行时加载
- MyApp.Common(.dll) – 由所有项目引用
您可以在MyApp.Common中定义画笔,隐式样式,模板等。
使用我的SharedResourceDictionary在所有项目中包含ResourceDictionary。 在设计时,它将为每个设计器加载ResourceDictionary,在运行时,ResourceDictionary将仅在必要时加载。
用法示例:
包含App.xaml中的SharedResourceDictionary
包括SharedResourceDictionary在内,设计器无法找到一些共享资源,例如在MyApp.Module1 / UserControl1.xaml中
资源:
/// /// Loads singleton instance of ResourceDictionary to current scope; /// public class SharedResourceDictionary : ResourceDictionary { /// /// store weak references to loaded ResourceDictionary, to ensure that ResourceDictionary won't be instanciated multiple times /// protected static Dictionary SharedResources = new Dictionary(); public string SharedSource { get { return _SharedSource; } set { if (_SharedSource != value) { _SharedSource = value; sharedSourceChanged(); } } } private string _SharedSource; private void sharedSourceChanged() { //ResourceDictionary will be instanciated only once ResourceDictionary sharedResourceDictionary; lock (SharedResources) { WeakReference weakResourceDictionary = null; if (SharedResources.ContainsKey(_SharedSource)) { weakResourceDictionary = SharedResources[_SharedSource]; } else { SharedResources.Add(_SharedSource, null); } if (weakResourceDictionary == null || !weakResourceDictionary.IsAlive) //load ResourceDictionary or get reference to exiting { sharedResourceDictionary = (ResourceDictionary)Application.LoadComponent(new Uri(_SharedSource, UriKind.Relative)); weakResourceDictionary = new WeakReference(sharedResourceDictionary); } else { sharedResourceDictionary = (ResourceDictionary)weakResourceDictionary.Target; } SharedResources[_SharedSource] = weakResourceDictionary; } if (Application.Current != null) { //if sharedResourceDictionary is defined in application scope do not add it to again to current scope if (containsResourceDictionary(Application.Current.Resources, sharedResourceDictionary)) { return; } } this.MergedDictionaries.Add(sharedResourceDictionary); } private bool containsResourceDictionary(ResourceDictionary scope, ResourceDictionary rs) { foreach (var subScope in scope.MergedDictionaries) { if (subScope == rs) return true; if (containsResourceDictionary(subScope, rs)) return true; } return false; } }
我发现有几个解决方案:
1)当你创建一个模块项目时,将App.xaml保留在项目中而不是删除它,并在那里实例化你的资源,就好像它本身就是它自己的应用程序一样(你也可以为项目添加一个新的Application类)你已经删除了它)。 当您的模块加载到shell中时,该文件将被忽略,因此它基本上只在设计时有效。 这在视觉工作室和混合中很有效,但如果你有很多模块,内存占用可能会成为一个问题。
2)使用设计时资源。 有关在此设置此信息的一些信息: http : //adamkinney.com/blog/2010/05/04/design-time-resources-in-expression-blend-4-rc/ 。 这仅提供混合支持,您的视图将被删除视觉工作室中的所有样式和格式。 这对我来说并不理想,因为我喜欢在visual studio中处理UI的某些方面。 似乎还没有一种手动设置设计时资源的文档化方法。
小型自有体验指南,用于将资源从Shell迁移到共享的essembly,并使设计师工作得很好
基于阅读此类问题并在相同/类似问题上搜索互联网的一些想法。 我写这个主要是因为问题2(下面),这与这个问题有关,恕我直言。
所以,我们有相同的设计,所有的风格和资源都在壳牌。 这产生了两个问题:
- XAML-Editor中的上下文帮助不可用(< - 找不到资源)
- 设计器无法正常显示(< - 未找到资源)
所以我们将所有样式迁移到共享程序集(Resources)。
要解决第一个问题,你需要像Liero提出的那样,即为每个UserControl添加资源字典。 我没有尝试他的SharedDictionary,但正常的ResourceDictionary肯定会带回上下文帮助并删除蓝色下划线。 然而,设计师仍然没有正确显示。
所以第二个问题。 在本文中仅描述了设计时为设计师带来样式的小技巧。 基本上,您将名为DesignTimeResources.xaml的资源字典添加到包含对资源的引用的项目中:
然后将其移动到Properties文件夹。 然后手动编辑项目文件并将此文件的项目更改为:
MSBuild:Compile Designer true
基本上它是Blend在添加设计时资源时会生成的文件。 VS无法创建它,虽然可以读得很好。 项目文件的编辑说你基本上不希望发布这个文件。
这里还有两个小问题,也许它会对某人有所帮助。
- 在将资源从Shell迁移到资源时,我们的Resources项目不会构建奇怪的错误,因为它找不到样式文件引用的UserControls(所有有问题的控件也在Resources项目中定义)。 之前从Shell引用它们时工作得很好。 问题是某些工具(如Resharper)会自动引用命名空间中的这些控件,如“
clr-namespace:XXX;assembly=Resources
”。 你应该删除“;assembly=Resources
” – 部分,因为它现在是同一个程序集。 -
我们已经在UserControls中处理了一些本地资源,如下所示:
所以起初我刚刚在这个块中添加了新的ResourceDictionary,它要求我提供一个x:Key。 我习惯于直接向UserControl.Resources添加资源,我没有意识到为了合并另一个字典,你需要
标记,通常你可以跳过。 所以它看起来像这样:
如果您希望为您的观点提供设计时数据,我建议您阅读本文 。 它显示了如何使用Blend在项目中创建设计时间数据,该数据未包含在应用程序的发布版本中。
希望能帮助到你。