2009-09-01 14 views
1

Je suis nouveau sur Prism et j'essaye d'héberger un contrôle Prisim dans un ElementHost. Il me semble qu'il manque quelque chose de très basique. J'ai un seul WinForm qui contient un ElementHost. Le code suivant est sous la forme:Comment utiliser Prisim dans un ElementHost

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     Bootstrapper bootstrapper = new Bootstrapper(); 
     bootstrapper.Run(); 

     var child = bootstrapper.Container.Resolve<Shell>(); 
     elementHost.Child = child; 

    } 

Le BootStrapper gère regisration

public class Bootstrapper : UnityBootstrapper 
{ 
    protected override DependencyObject CreateShell() 
    { 
     Container.RegisterType<MyView>(); 
     var shell = Container.Resolve<Shell>(); 
     return shell; 
    } 

    protected override IModuleCatalog GetModuleCatalog() 
    { 
     ModuleCatalog catalog = new ModuleCatalog(); 
     catalog.AddModule(typeof(MyModule)); 
     return catalog; 
    } 
} 

Le MyView.xaml est rien de plus qu'une étiquette à ce stade.

Shell.xaml est un UserControl qui contient le code XAML suivant:

<ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion" /> 

Le code du module est minimal:

public class MyModule : IModule 
{ 
    private readonly IRegionViewRegistry _regionViewRegistry; 

    public MyModule(IRegionViewRegistry registry) 
    { 
     _regionViewRegistry = registry; 
    } 

    public void Initialize() 
    { 
     _regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(MyView)); 
    } 
} 

J'ai traçais profondément dans le code Prism essayant de comprendre pourquoi la vue n'est jamais définie dans la région. Est-ce que je manque quelque chose de basique?

Répondre

4

La raison est ce code dans Prism:

private static bool RegionManager::IsInDesignMode(DependencyObject element) 
{ 
    // Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode. 
    return DesignerProperties.GetIsInDesignMode(element) || Application.Current == null 
     || Application.Current.GetType() == typeof(Application); 
} 

La raison est que pour la non-application WPF est le Application.Current NULL!

La solution:

  1. Créer une classe vide qui héritera de System.Windows.Application. (Nom n'a pas d'importance):

Au point d'entrée à un plug-in exécuter le code suivant:

public class MyApp : System.Windows.Application 
{ 
} 

if (System.Windows.Application.Current == null) 
{ 
    // create the Application object 
    new MyApp(); 
} 

Ceci est - maintenant vous avez un Application.Current qui n'est pas null et ce n'est pas égal à typeof (Application).

+0

Vous faites ma journée. Ce hack curieux fonctionne pour moi aussi :-) –

0

@Mark Lindell Ci-dessus a travaillé pour moi. Les seules choses que j'ai dû changer sont en bas.

Mon bootstrapper

public class Bootstrapper : UnityBootstrapper 
    { 
     protected override DependencyObject CreateShell() 
     { 
      return this.Container.Resolve<Shell>(); 
     } 

     protected override void InitializeShell() 
     { 
      base.InitializeShell();  
      if (System.Windows.Application.Current == null) 
      { 
       // create the Application object 
       new HelloWorld.Myapp(); 
      } 

      //App.Current.MainWindow = (Window)this.Shell; 
      //App.Current.MainWindow.Show(); 
      //MainWindow = (Window)this.Shell; 

     }  

     protected override void ConfigureModuleCatalog() 
     { 
      base.ConfigureModuleCatalog(); 

      ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog; 
      moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule)); 
     } 

et ma forme de classe

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      //Create the ElementHost control for hosting the WPF UserControl 
      ElementHost host = new ElementHost(); 
      host.Dock = DockStyle.Fill; 

      Bootstrapper bootstrapper = new Bootstrapper(); 
      bootstrapper.Run(true); 

      //var uc = bootstrapper.Container.Resolve<Shell>(); This line threw error 

      //Create the WPF UserControl.   

          HelloWorld.Shell uc = new HelloWorld.Shell(); 

      //Assign the WPF UserControl to the ElementHost control's Child property. 
      host.Child = uc; 

      //Add the ElementHost control to the form's collection of child controls. 
      this.Controls.Add(host); 
     } 
    } 


     } 

Et juste pour être clair, j'ai ajouté ci-dessous classe dans l'application WPF PRISM contenant Shell.

public class MyApp : System.Windows.Application 
{ 
} 

Edit: Notez que le gestionnaire de la méthode de charge (de forme) doit être créé par forme rightclicking, Dans la fenêtre des propriétés, à des événements et à double charge de clicl. La copie et le collage du gestionnaire d'événements de chargement ne fonctionnent pas.