如何在设计时在棱镜模块中使用资源字典?

我在一个silverlight应用程序中使用prism框架,在单独的XAP中有多个模块。

我在我的shell项目中定义了一个资源字典。 在我的模块中,我可以很好地使用资源,但由于模块与shell分离,直到它们在运行时加载,设计器不会显示它们或识别它们。

有没有办法让模块在设计时知道我的资源而不在每个视图xaml中合并我的资源文件?

我的资源文件位于“常见”项目中。

我想我肯定有设计时资源的解决方案。

优点:

  1. 它适用于任何基于模块(MEF,UNITY ..)的应用程序。
  2. 它适用于任何设计师(Visual Studio,Blend ..)
  3. 它不会创建相同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(下面),这与这个问题有关,恕我直言。

所以,我们有相同的设计,所有的风格和资源都在壳牌。 这产生了两个问题:

  1. XAML-Editor中的上下文帮助不可用(< - 找不到资源)
  2. 设计器无法正常显示(< - 未找到资源)

所以我们将所有样式迁移到共享程序集(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在项目中创建设计时间数据,该数据未包含在应用程序的发布版本中。

希望能帮助到你。