Pergunta

Uma vez que eu tenho um aplicativo de shell e um par de projectos módulo separado usando Microsoft CompoisteWPF (Prism v2) ...

Ao receber um comando, um módulo cria um novo ViewModel e adiciona-lo para uma região através do gerenciador região.

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

Eu pensei que eu poderia, então, criar um dicionário de recursos dentro do módulo e criar um modelo de dados para exibir uma visão para o tipo de vista do modelo que foi carregado (veja abaixo XAML). Mas, quando o modelo de exibição é adicionado à vista, tudo que eu vejo é os modelos de exibição namespace impresso.

<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>

Editar:

Eu posso fazê-lo funcionar, adicionando ao 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>

O que é bom, mas isso significa que à medida que novos módulos são criados, o arquivo App.xaml precisa ser adicionado ao. O que eu estou procurando é uma forma de módulos, como eles carregam para adicionar dinamicamente às as Application.Resources. Isso é possível?

Foi útil?

Solução 2

Dentro da inicialização de cada módulo, você pode adicionar aos recursos do aplicativo:

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

Ou se você seguir uma convenção de cada módulo tem um dicionário de recurso chamado "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"))
                              });
              });
}

Outras dicas

Para evitar seu aplicativo shell de ter que saber nada sobre seus módulos e os módulos de estender a mão para o shell de qualquer forma, eu fornecer uma interface para seus módulos como este:

IMergeDictionaryRegistry
{
     void AddDictionaryResource(Uri packUri);
}

Você pediria para esta interface em seu código do módulo:

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");
     }
}

Você, então, implementar isso no seu shell para fazer isso:

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

E então, finalmente, em sua ConfigureContainer de Bootstrapper:

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

Isso vai te dar a funcionalidade desejada e seu Shell e seu módulo permanecerá independentes um do outro. Isto tem a vantagem de ser mais testáveis ??em que você não tem necessidade de girar um Application para testar o seu código do módulo (IMergeDictionaryRegistry apenas simulada e está feito).

Deixe-nos saber como isso vai para você.

Isso tudo parece um monte de trabalho!

Pessoalmente, eu só declarar um dicionário de recursos na seção UserControl.Resources do meu ponto de vista como este ...

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

que se fundiu dicionário pontos, em seguida, a todos os recursos que precisa para incluir.

<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>

Você iria declarar os seus modelos de dados lá, eu acho.

HTH.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top