2017-11-17 19 views
0

Ich habe 3 Viewmodels:Warum bindet Caliburn Micro trotz der gleichen Namenskonventionen einige Ansichten ein, aber keine anderen?

  • App.ViewModels.LoginViewModel
  • App.ViewModels.NavigationViewModel
  • App.ViewModels.AbcViewModel

und 3 Aufrufe:

  • App.Views.LoginView
  • App.Views.NavigationView
  • App.Views.AbcView

In meinem AppBootstrapper wird Loginview wie so geladen:

protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) 
{ 
    var windowManager = IoC.Get<IWindowManager>(); 
    var loginModel = IoC.Get<ILogin>("Login"); 

    windowManager.ShowWindow(loginModel, "LoginView"); 
} 

Doch diese gibt, dass die Ansicht nicht für das Ansichtsmodell gefunden werden. Es sei denn, ich ändere den Namespace des LoginView in App.Views.Login.LoginView und belasse den VM-Namespace so wie er ist. Es funktioniert dann gut.

Nach einer erfolgreichen Anmeldung verwende ich den gleichen Prozess, um mein NavigationViewModel zu laden. (Nach dem Namespace in den App.Views.Navigation.NavigationViewModel geändert haben, so dass es tatsächlich funktioniert)

Derzeit dies lässt mich mit den folgenden Namensräume für die Ansichten:

  • App.Views.Login. Loginview
  • App.Views.Navigation.NavigationView
  • App.Views.AbcView

NavigationViewModel ist ein Leiter, eine Liste von Viewmodels und eine TabControl auf die anzeigen, um sie anzuzeigen.

Leider muss ich dann manuell mein AbcViewModel an die View binden, sonst wird nichts angezeigt. Zum Beispiel:

AbcView abcv= new AbcView(); 
AbcViewModel abcvm= IoC.Get<AbcViewModel>("Abc"); 
ViewModelBinder.Bind(abcvm, abc, null); 

Ich will alles den Caliburn Ansichtsmodell ersten Ansatz zu tun mit, so dass das Hinzufügen neue Viewmodel und Ansichten wir kümmern müssen manuell die Ansicht nicht zu binden. Ich habe mich an die Struktur gehalten und es funktioniert nicht. Wo gehe ich falsch?

Grundsätzlich gibt es eine Möglichkeit, die Calibrun erstellen und dann meine Ansicht binden kann, wenn ich mein ViewModel erstelle? Muss ich irgendwie den ViewLocator für jedes meiner Modelle aufrufen? Wenn ja, wie unterscheidet sich das von der manuellen Bindung, die ich gerade mache?

Weiß jemand von einem vollständigen Beispiel (Ganzes Projekt) eines Ansichtsmodells erstes caliburn Projekt, das ich schleichen kann?

Jede Hilfe geschätzt, danke im Voraus.

Matt

+0

Sie müssen nichts tun, außer Bootstrapper zu konfigurieren. Caliburn.Micro verwendet die Konvention: 'Views/xyzView' maps zu' ViewModels/xyzViewModel'. Stellen Sie außerdem sicher, dass Sie Ihren Startpunkt von 'App.xaml' entfernen und' ResourceDictionary' hinzufügen. Ich habe eine [Vorlage] (https://github.com/fcin/Caliburn.Micro-DI-Example) erstellt, um mit caliburn.micro mit Dependency Injection zu beginnen – FCin

+0

Prost für die schnelle Antwort. Hatte einen kurzen Blick auf Ihr Beispiel, wird später ein richtiges Aussehen haben, ich kann schon sehen, Ihr Bootstrapper ist viel einfacher als meins. Ich verwende auch einen CompositionContainer und habe dies mit einem CompositionBatch gekoppelt. 'Container = new CompositionContainer (neu AggregateCatalog (AssemblySource.Instance.Select (x => new Assembly (x)) OfType ()).);' Ich verwende dann: 'Charge. AddExportValue > (() => container.GetExportValue ()); ' Um alle meine ViewModels (außer Navigation und Login) zum Container hinzuzufügen. –

+0

Behalten Sie Ihre ViewModels und Views in derselben Lösung? Sie brauchen 'CompositionContainer' nicht. 'SimpleContainer' reicht aus, um Typen zu registrieren, die injiziert werden sollen, wenn sie sich im selben Projekt befinden. – FCin

Antwort

0

Sie brauchen keine Views/Viewmodels, sich zu binden, nimmt Caliburn.Micro darum gekümmert. Sie müssen nur Caliburn.Micro, wo Ihre Startklasse ist durch Überschreiben OnStartup in Ihrer Bootstrapper Klasse (siehe tutorial) sagen.

Sie haben auch ResourceDictionary mit Bootstrapper Klasse in App.xaml zur Verfügung zu stellen und entfernen Startup:

<Application.Resources> 
     <!--Declare your bootstrapper class--> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary> 
        <local:YourBootstrapperClass x:Key="bootstrapper" /> 
       </ResourceDictionary> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

Ihre Bootstrapper Klasse muss von BootstrapperBase ableiten und Initialize() in Konstruktor aufrufen. Das sollte für Caliburn.Micro reichen, Ansichten/viewmodels zu binden.


Außerdem, wenn Sie Dependency Injection in Ihrem Projekt verwenden möchten, können Sie Setup ein SimpleContainer und registrieren Typen möchten Sie injizieren. Sie können dies tun, in Bootstrapper:

public class Bootstrapper : BootstrapperBase 
    { 
     // Container for your registered types. 
     private SimpleContainer _container = new SimpleContainer(); 

     public Bootstrapper() 
     { 
      Initialize(); 
     } 

     protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) 
     { 
      // Tells Caliburn.Micro where the starting point of your application is. 
      DisplayRootViewFor<ShellViewModel>(); 
     } 

     protected override void Configure() 
     { 
      // Register types you want to inject. 
      _container.Singleton<IWindowManager, WindowManager>(); 
      _container.Singleton<IEventAggregator, EventAggregator>(); 
      base.Configure(); 
     } 

     protected override object GetInstance(Type service, string key) 
     { 
      // This is called every time a dependency is requested. 
      // Caliburn.Micro checks if container contains dependency and if so, returns it. 
      var instance = _container.GetInstance(service, key); 
      if (instance != null) 
       return instance; 

      throw new InvalidOperationException("Could not locate any instances."); 
     } 

     protected override IEnumerable<object> GetAllInstances(Type service) 
     { 
      // Get all registered classes... 
      return _container.GetAllInstances(service); 
     } 

     protected override void BuildUp(object instance) 
     { 
      _container.BuildUp(instance); 
     } 

    } 

Danach kann man einfach dependecies über Konstruktor wie diese injiziert:

public class ShellViewModel 
{ 
    public ShellViewModel(IEventAggregator eventAggregator) 
    { 
      // You can use eventAggregator here. It is already injected. 
    } 
} 

Caliburn.Micro verwendet Namenskonvention, so dass es automatisch Views/Viewmodel zu entdecken. Sie sollten folgende Ordner haben: Views und ViewModels und Ihre Klassen sollten YourClassView und YourClassViewModel heißen. Auf diese Weise kann Caliburn.Micro sie finden. Also, wenn Sie Setup OnStartup wie folgt aus:

protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) 
{ 
    DisplayRootViewFor<ShellViewModel>(); 
} 

Dann müssen Sie Ihre Viewmodel in ViewModels/ShellViewModel sitzen und Ihre Sicht für diese Ansichtsmodell muss in Views/ShellView sitzen.

Verwandte Themen