2009-07-23 11 views
13

Dado que tengo una aplicación de shell y un par de proyectos de módulo por separado utilizando Microsoft CompoisteWPF (Prisma v2) ...Composite WPF (Prism) plantillas de recursos del módulo de datos

Al recibir un comando, un módulo crea una nueva ViewModel y lo agrega a una región a través del administrador de región.

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

pensé que entonces podría crear un diccionario de recursos dentro del módulo y configurar una plantilla de datos para mostrar una vista para el tipo de vista del modelo que se cargó (ver más abajo XAML). Pero cuando se agrega el modelo de vista a la vista, todo lo que obtengo es el espacio de nombres de los modelos de vista impreso.

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

puedo conseguir que funcione mediante la adición a la 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> 

Lo cual está bien, pero significa que a medida que los nuevos módulos son creados, la App. El archivo xaml debe agregarse a. Lo que estoy buscando es una forma de que los módulos se carguen para agregar dinámicamente a la Aplicación.Recursos. es posible?

Respuesta

5

Dentro de la inicialización de cada módulo, se pueden añadir a los recursos de la aplicación:

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

O si usted sigue una convención de cada módulo tiene un diccionario de recursos denominado "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")) 
           }); 
       }); 
} 
+0

La primera parte de su respuesta requiere que su módulo alcance la Aplicación. Recomendaría en contra de esto ya que no se puede evaluar. El segundo enfoque es más apropiado. –

19

Para evitar su aplicación cáscara de tener que saber nada acerca de sus módulos y los módulos de llegar en la cáscara de ninguna manera, me proporcionan una interfaz para los módulos de la siguiente manera:

IMergeDictionaryRegistry 
{ 
    void AddDictionaryResource(Uri packUri); 
} 

Usted 'd pedir esta interfaz en el código del 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"); 
    } 
} 

a continuación, poner en práctica esta en la shell para hacer esto:

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

Y, por último, en ConfigureContainer de su programa previo:

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

Esto le dará la funcionalidad que desea y su Shell y su módulo seguirá siendo independientes entre sí. Esto tiene el beneficio adicional de ser más comprobable, ya que no es necesario girar un Application para probar el código de su módulo (simplemente se burla de IMergeDictionaryRegistry y listo).

Háganos saber cómo esto sirve para usted.

+0

Gracias. WPF sabe cómo renderizar ViewModel utilizando DataTemplate (consulte: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097). El problema es hacer que la aplicación conozca DataTemplate en otro ensamblado. He editado la publicación para proporcionar más detalles. – Oll

+0

Oh, veo lo que estás haciendo. Es posible que deba proporcionar alguna interfaz (IMergeDictionaryRegistration con un método que acepte un paquete URL) a sus módulos y anexarlos al diccionario de recursos de su aplicación. Solo una teoría –

+0

También ... Tengo curiosidad de cómo esto va para ti. Haznos saber. Ese es un enfoque interesante. –

1

¡Parece un montón de trabajo!

Personalmente, acabo de declarar un diccionario de recursos en la sección de mi vista UserControl.Resources así ...

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

que se fusionaron diccionario después señala a cualquier recurso que necesito 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> 

Se podría declarar las plantillas de datos ahí supongo.

HTH.

Cuestiones relacionadas