2009-07-23 8 views
13

Étant donné que j'ai une application shell et un couple de projets de modules séparés à l'aide de Microsoft CompoisteWPF (Prism v2) ...modèles de données de ressources du module Composite WPF (Prism)

Sur réception d'une commande, un module crée une nouvelle ViewModel et l'ajoute à une région via le gestionnaire de région.

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

Je pensais que je pourrais alors créer un dictionnaire de ressources dans le module et mettre en place un modèle de données pour afficher une vue pour le type de modèle de vue qui a été chargé (voir ci-dessous XAML). Mais lorsque le modèle de vue est ajouté à la vue, tout ce que j'obtiens est l'espace de noms des modèles de vue imprimé.

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

Edit:

Je peux l'obtenir pour travailler en ajoutant à 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> 

Ce qui est bien, mais cela signifie que les modules sont créés en tant que nouveaux, l'App. Le fichier xaml doit être ajouté. Ce que je cherche est un moyen pour les modules, car ils chargent pour ajouter dynamiquement à l'Application.Resources. Est-ce possible?

Répondre

5

Dans l'initialisation de chaque module, vous pouvez ajouter aux ressources de l'application:

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

Ou si vous suivez une convention de chaque module dispose d'un dictionnaire de ressources appelé « 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 première partie de votre réponse nécessite que votre module accède à l'application. Je recommanderais contre cela car il est impossible à tester. La deuxième approche est plus appropriée. –

19

Pour éviter que votre application shell d'avoir à connaître quoi que ce soit au sujet de vos modules et vos modules de qui tend vers la coquille de quelque façon, je fournir une interface à vos modules comme ceci:

IMergeDictionaryRegistry 
{ 
    void AddDictionaryResource(Uri packUri); 
} 

Vous « d demander cette interface dans votre code du module:

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

Vous pouvez ensuite mettre en œuvre dans votre shell pour faire ceci:

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

Et puis enfin, dans votre ConfigureContainer de Bootstrapper:

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

Vous obtiendrez la fonctionnalité que vous voulez et votre Shell et votre module demeureront indépendantes les unes des autres. Cela a l'avantage d'être plus testable dans le sens où vous n'avez pas besoin de lancer un Application pour tester le code de votre module (juste simulé IMergeDictionaryRegistry et vous avez terminé).

Faites-nous savoir comment cela se passe pour vous.

+0

Merci. WPF sait comment rendre le ViewModel en utilisant le DataTemplate (voir: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097). Le problème consiste à faire connaître à l'application le DataTemplate dans un autre assembly. J'ai modifié le post pour fournir plus de détails. – Oll

+0

Oh, je vois ce que vous faites. Vous devrez peut-être fournir une interface (IMergeDictionaryRegistration avec une méthode qui accepte une URL de pack) à vos modules et les ajouter au dictionnaire de ressources de votre application. Juste une théorie. –

+0

Aussi ... Je suis curieux de savoir comment cela se passe pour vous. Laissez nous savoir. C'est une approche intéressante. –

1

Tout cela semble beaucoup de travail!

Personnellement, je viens de déclarer une section dictionnaire de ressources en vue de mon UserControl.Resources comme ça ...

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

qui a fusionné le dictionnaire désigne alors toutes les ressources dont j'ai besoin d'inclure.

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

Vous souhaitez déclarer vos modèles de données là-bas je suppose.

HTH.