2016-06-24 17 views
3

Ich frage das hier, weil ich ratlos bin, weil ich versucht habe, das herauszufinden. Ich habe gesucht und alles, was auftaucht, sind Dinge, die Sinn machen, aber auch nicht auf meine Situation zutreffen.Warum wird OnActivate nicht aufgerufen?

Ich verwende WPF mit MVVM und Caliburn.Micro. Ich habe ein Shell-Fenster mit einem entsprechenden View-Modell, das ist ein Conductor<Screen>.Collection.OnceActive und ein Bildschirm, der von Screen erbt. Ich rufe ActivateItem innerhalb des Konstruktors des Dirigenten an, um den folgenden Bildschirm anzuzeigen, es zeigt den Bildschirm korrekt aber ruft die Bildschirmüberschreibung für OnActivate nie auf und die IsActive Eigenschaft des Bildschirms wird auf False festgelegt.

Dies geschieht nur das erste Mal, dass ich ActivateItem vom Conductor nennen, alle weiteren Anrufe rufen richtig OnActivate und OnDeactivate.

Das macht keinen Sinn für mich und ich habe keine Ahnung, was vor sich geht. Ich habe die Lösung gereinigt, neu aufgebaut und sogar neu gestartet, aber es funktioniert immer noch nicht richtig. Unten ist der Code:

Eltern Conductor

[Export] 
public sealed class ShellViewModel : Conductor<Screen>.Collection.OneActive, IHandle<SimpleMessage> 
{ 
    private readonly DashboardViewModel m_Dash; 
    private readonly LoginViewModel m_Login; 
    private readonly IEventAggregator m_MsgBus; 

    [ImportingConstructor] 
    public ShellViewModel(DashboardViewModel dash, LoginViewModel login, IEventAggregator msgBus) 
    { 
     this.m_MsgBus = msgBus; 
     this.m_Dash = dash; 
     this.m_Login = login; 

     this.ActivateItem(this.m_Login); 
    } 

    protected override void OnActivate() 
    { 
     this.m_MsgBus.Subscribe(this); //called correctly 
    } 

    protected override void OnDeactivate(bool close) 
    { 
     this.m_MsgBus.Unsubscribe(this); //called correctly 
    } 

    public void Handle(SimpleMessage message) 
    { 
     switch (message) 
     { 
      case SimpleMessage.LoginSuccess: 
       this.ActivateItem(this.m_Dash); 
       break; 

      case SimpleMessage.Logout: 
       this.ActivateItem(this.m_Login); 
       break; 
     } 
    } 
} 

Kinder Bildschirm

[Export] 
public sealed class LoginViewModel : Screen 
{ 
    private readonly IEventAggregator m_MsgBus; 

    [ImportingConstructor] 
    public LoginViewModel(IEventAggregator msgBus) 
    { 
     this.m_MsgBus = msgBus; 
    } 

    protected override void OnActivate() 
    { 
     //NOT called the first time, but is called every other time 
     MessageBox.Show("ACTIVATE TEST"); 
    } 

    protected override void OnDeactivate(bool close) 
    { 
     //NOT called the first time, but is called every other time 
     MessageBox.Show("DEACTIVATE TEST"); 
    } 

    public void CmdLogin(string password) 
    { 
     this.m_MsgBus.PublishOnUIThread(SimpleMessage.LoginSuccess); 
    } 

    public string Username { get; set; } 

    public string Password { get; set; } 
} 

UPDATE

ich die Caliburn Micro Quelle heruntergeladen, so konnte ich in den Schritt ActivateItem Funktion und sehen, was vor sich geht. Aus irgendeinem Grund, wenn ich zum ersten Mal ActivateItem vom Dirigenten anrufen, wird die IsActive Eigenschaft des Dirigenten auf false gesetzt, was bewirkt, dass Caliburn den Aufruf der OnActivate Überschreibung überspringt. Ich habe keine Ahnung, warum die Immobilie falsch wäre.

ConductorBaseWithActiveItem.cs

protected virtual void ChangeActiveItem(T newItem, bool closePrevious) { 
    ScreenExtensions.TryDeactivate(activeItem, closePrevious); 

    newItem = EnsureItem(newItem); 

    //Problem is here, IsActive is false the first time around in the conductor 
    if(IsActive) 
     ScreenExtensions.TryActivate(newItem); 

    activeItem = newItem; 
    NotifyOfPropertyChange("ActiveItem"); 
    OnActivationProcessed(activeItem, true); 
} 

Es sieht aus wie der Grund IsActive im Conductor falsch ist, weil mein Dirigent der Stammansicht ist, die DisplayRootViewFor erstellt wird und es sieht so aus, dass Funktion die nicht gesetzt ist IsActive Eigenschaft zu wahr.

Also, ich weiß, dass ich das einfach falsch implementiere und ein Conductor nicht die Root View sein kann/sollte? Muss ich ein zweites Kind sehen, welches der Dirigent ist (das scheint ein bisschen viel zu sein)?

Antwort

3

Ich fand es heraus und es war im Grunde ich denke nicht. Das Aktivieren einer Ansicht im Konstruktor der Leiter-/Stammansicht funktioniert nicht ordnungsgemäß, weil sie noch nicht aktiviert wurde. IsActive wird nicht auf True gesetzt, bis die/root-Ansicht des Leiters/OnActivate aufgerufen wird.

Dies kann zu einem bestimmten Zeitpunkt problematisch sein, da der Leiter nicht aktiv ist, auch wenn OnInitialize aufgerufen wird und das ist die eine Zeit Init-Funktion und OnActivate könnte mehrmals aufgerufen werden. In meinem Fall ist es in Ordnung, weil mein Leiter die Grundansicht ist, so dass OnActivate nur einmal aufgerufen wird.

Moral der Geschichte ist, rufen Sie nicht ActivateItem im Konstruktor eines Dirigenten, wenn der Leiter eine Root-Ansicht ist.

+0

Ich hatte auch damit zu kämpfen, bis ich Ihre Antwort fand. Das war letzte Woche. Heute habe ich etwas anderes recherchiert und festgestellt, dass dieses Verhalten in der Dokumentation unter http://caliburnmicro.com/documentation/composition erwähnt wird: > Wenn Sie einen Gegenstand in einem Leiter aktivieren, der selbst nicht aktiv ist, wird dieser Gegenstand nicht tatsächlich aktiviert werden, bis der Leiter aktiviert wird. –