14

鉴于我有一个 shell 应用程序和几个使用 Microsoft CompoisteWPF (Prism v2) 的单独模块项目......

收到命令后,模块会创建一个新的 ViewModel 并通过区域管理器将其添加到区域中。

var viewModel = _container.Resolve<IMyViewModel>();
_regionManager.Regions[RegionNames.ShellMainRegion].Add(viewModel);

我认为我可以在模块中创建一个资源字典并设置一个数据模板来显示加载的视图模型类型的视图(见下面的 xaml)。但是当视图模型被添加到视图中时,我得到的只是打印出来的视图模型命名空间。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:Modules.Module1.ViewModels"
    xmlns:vw="clr-namespace:Modules.Module1.Views"
>
    <DataTemplate DataType="{x:Type vm:MyViewModel}">
        <vw:MyView />
    </DataTemplate>
</ResourceDictionary>

编辑:

我可以通过添加到 App.xaml 来让它工作

<Application.Resources>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/Module1;component/Module1Resources.xaml"/>
        <ResourceDictionary Source="pack://application:,,,/Module2;component/Module2Resources.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</Application.Resources>

这很好,但这意味着随着新模块的创建,需要添加 App.xaml 文件。我正在寻找的是模块的一种方式,因为它们加载以动态添加到 Application.Resources。这可能吗?

4

3 回答 3

21

为了避免您的 shell 应用程序必须了解有关您的模块的任何信息以及您的模块以任何方式进入 shell,我将为您的模块提供一个接口,如下所示:

IMergeDictionaryRegistry
{
     void AddDictionaryResource(Uri packUri);
}

你会在你的模块代码中要求这个接口:

public class MyModule : IModule
{
     IMergeDictionaryRegistry _merger;
     public MyModule(IMergeDictionaryRegistry merger)
     {
          _merger = merger;
     }

     public void Initialize()
     {
          _merger.AddDictionaryResource(new Uri("pack://application:,,,/Module1;component/Module1Resources.xaml");
     }
}

然后,您将在您的 shell 中实现它来执行此操作:

public MergeDictionaryRegistry : IMergeDictionaryRegistry
{
     public void AddDictionaryResource(Uri packUri)
     {
          Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
          {
               Source = packUri;
          });
     }
}

最后,在您的引导程序的 ConfigureContainer 中:

public override void ConfigureContainer()
{
     base.ConfigureContainer();
     Container.RegisterType<IMergeDictionaryRegistry, MergeDictionaryRegistry>();
}

这将为您提供所需的功能,并且您的 Shell 和您的模块将保持相互独立。这具有更可测试的额外好处,因为您无需启动 anApplication来测试您的模块代码(只需模拟IMergeDictionaryRegistry即可完成)。

让我们知道这对您有何影响。

于 2009-07-23T16:01:38.840 回答
6

在每个模块的初始化中,您可以添加到应用程序资源:

Application.Current.Resources.MergedDictionaries
                .Add(new ResourceDictionary
                {
                    Source = new Uri(
                        @"pack://application:,,,/MyApplication.Modules.Module1.Module1Init;component/Resources.xaml")
                });

或者,如果您遵循每个模块的约定,那么每个模块都有一个名为“Resources.xmal”的资源字典......

protected override IModuleCatalog GetModuleCatalog()
{
    var catalog = new ModuleCatalog();

    AddModules(catalog,
               typeof (Module1),
               typeof(Module2),
               typeof(Module3),
               typeof(Module4));

    return catalog;
}

private static void AddModules(ModuleCatalog moduleCatalog,
    params Type[] types)
{
    types.ToList()
         .ForEach(x =>
             {
                 moduleCatalog.AddModule(x);
                 Application.Current.Resources.MergedDictionaries
                     .Add(new ResourceDictionary
                              {
                                  Source = new Uri(string.Format(
                                                       @"pack://application:,,,/{0};component/{1}",
                                                       x.Assembly,
                                                       "Resources.xaml"))
                              });
              });
}
于 2009-08-19T10:30:03.150 回答
2

这一切似乎都是一项艰巨的工作!

就个人而言,我只是在我的视图UserControl.Resources部分中声明一个资源字典,如下所示......

<UserControl.Resources>
    <ResourceDictionary Source="../Resources/MergedResources.xaml" />
</UserControl.Resources>

然后,该合并字典指向我需要包含的任何资源。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Iconography.xaml" />
    <ResourceDictionary Source="Typeography.xaml" />
</ResourceDictionary.MergedDictionaries>

我猜你会在那里声明你的数据模板。

HTH。

于 2010-09-09T14:42:49.163 回答