2016-06-01 15 views
2

Ich benutze MVVM Framework Caliburn Micro in meiner gesamten Anwendung mit ViewModel zuerst (oder so dachte ich). Wenn ich jedoch Probleme mit einem Dialog hatte, der TryClose(true) fehlschlägt, sein Elternfenster zu schließen und stolperte über diese Frage, die mein Problem perfekt umriss, bekomme ich auch die "TryClose erfordert einen übergeordneten IConductor oder eine Ansicht mit einer Close-Methode oder IsOpen-Eigenschaft ".Caliburn Micro, Verwendung von ContentControl (oder Anzeige von 'Sub' ViewModel) mit ViewModel Zuerst

Caliburn.Micro - ShowDialog() how to close the dialog?

aber ich bin nicht sicher, wie genau die Lösung zu implementieren. Die Antwort lautet:

Entfernen Sie die cal: Bind.Model und cal: View.Model Bindungen ...

diese Bindungen ist eine Ansicht-First-Ansatz stellte sich heraus, das ich war nicht bewusst, dass ich es tat. Hier ist ein Beispiel meiner säumige Dialog:

<UserControl ... Height="206" Width="415"> 
    <Grid Margin="20"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="AUTO" /> 
     </Grid.RowDefinitions> 
     <Grid Grid.Row="1"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 
      <Button x:Name="Okay" Content="Okay" Width="100" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
      <Button x:Name="Cancel" Content="Cancel" Width="100" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
     </Grid> 
     <ContentControl cal:View.Model="{Binding TimeSpanViewModel}"/> 
    </Grid> 
</UserControl> 

Es ist nur ein Wrapper mit einem in Ordnung und Abbruchtaste für einen bereits vorhandenen Viewmodel (wer Ansicht von Caliburn gelöst ist, also dachte ich ich tue Ansichtsmodell zuerst). Wenn ich diese cal:View.Model Bindung entferne, erhalte ich tatsächlich die Fähigkeit, mein Dialogfeld zu schließen, aber ich verliere den ganzen tatsächlichen Inhalt. Ich verwende das ContentControl, um Dinge in meiner gesamten Anwendung anzuzeigen (in ItemsControls, Dialogfeldern, Pop-ups usw.).

Meine Frage ist, wie sollte ich ein ViewModel in einem ViewModel ersten Caliburn anzeigen?

Edit: Ich bin die Anzeige der DialogViewModel (die Bildschirm erbt) wie das Windowmanager mit so:

[Export(typeof(IWindowManager))] 
public class AppWindowManager : MetroWindowManager, IDialogManager 
{ 
    AppViewModel Content { get; set; } 

    public AppWindowManager() 
    { 

    } 

    public override MetroWindow CreateCustomWindow(object view, bool windowIsView) 
    { 
     if (windowIsView) 
     { 
      return view as MainWindowContainer; 
     } 

     MainWindowContainer window = new MainWindowContainer(); 
     //{ 
     window.Content = view; 
     //}; 

     return window; 
    } 

    public override bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null) 
    { 
     Window window = CreateWindow(rootModel, true, context, settings); 

     return window.ShowDialog(); 
    } 

    public object ShowCustomDialog(object rootModel, string title, bool showWindowsOptions = true) 
    { 
     dynamic settings = new ExpandoObject(); 
     settings.Title = title; 
     settings.ShowCloseButton = showWindowsOptions; 
     settings.ShowMaxRestoreButton = showWindowsOptions; 
     settings.ShowMinButton = showWindowsOptions; 
     settings.SizeToContent = SizeToContent.WidthAndHeight; 
     return ShowDialog(rootModel, null, settings); 
    } 

    public ILoadingDialogViewModel CreateLoadingDialogManager() 
    { 
     return new LoadingDialogViewModel(this); 
    } 
} 
+0

Wahrscheinlich sollten Sie weitere Details hinzufügen: Sind Sie ein 'conductor' mit Ihrem Dialog angezeigt werden? Welches Problem hast du mit "TryClose"? Siehst du die gleiche Botschaft von der anderen Frage? –

+0

Dies ist das Ansichtsmodell zuerst, da Sie kein Benutzersteuerelement zum Angeben der Ansicht verwenden und eine Sicht in das Inhaltssteuerelement basierend auf dem Ansichtsmodell laden. Es wird nur zuerst angezeigt, wenn Sie ein Benutzersteuerelement bereitstellen, an das Sie ein Anzeigemodell an/für binden/erstellen möchten. Hat Ihr Kind viewmodel einen Candeactivate Hook? – Charleh

+0

Das untergeordnete Element (TimeSpanViewModel) erbt PropertyChangedBase, und das Dialogfeld ViewModel, das es hostet (siehe obigen Code), implementiert Screen. Ich habe Deaktivierungshaken bei der Kalibrierung nicht berührt. – Joe

Antwort

3

die Hauptfrage zu beantworten

wie soll ich in ein ein Ansichtsmodell werden Anzeige ViewModel zuerst Caliburn?

Ich gehe davon aus TimeSpanViewModel ist eine Eigenschaft, die Sie auf Ihrem Ansichtsmodell haben, das eine [Import] hat (und das Ansichtsmodell exportiert selbst)? Ich denke, dass Sie cal:View.Model="{Binding TimeSpanViewModel}" zu x:Name="TimeSpanViewModel" ändern sollten. Auch wenn dies das Problem möglicherweise nicht löst, ist es das Richtige und Caliburn stellt sicher, dass es korrekt gebunden ist.

Ich habe versucht, Ihr Problem zu reproduzieren, aber sogar auf Ihre Weise funktioniert es für mich. Warum es nicht so funktioniert, wie Sie es gerade tun, ist eine gute (zweite) Frage.

Das größte Problem könnte Ihr AppWindowManager sein, wenn das Fenster, das Sie dort erstellen, nicht den korrekten Caliburn-Code durchläuft und nicht korrekt gebunden wird. Da es viel Code fehlt, bin ich mir nicht einmal sicher was AppViewModel Content { get; set; } da macht, meistens kann ich nur spekulieren. Haben Sie versucht, die Standard-WindowManager-Implementierung zu verwenden, nur um zu sehen, ob sie damit funktioniert?

+0

Ich denke, Sie könnten mit dem Fenstermanager das Problem haben, ich ' Versuchen Sie, die Standardimplementierung zu verwenden. Ich habe versucht mit x: Name = "TimeSpanViewModel" und bekomme die gleichen Ergebnisse. Das TimeSpanViewModel ist in der Tat eine Eigenschaft auf dem DialogViewModel. Ich bin mir nicht sicher, was du mit [Import] meinst. Ich habe die ViewModel- und View-Dateien (wenn ich die View-Datei falsch male) kann Caliburn es nicht verkabeln und meldet "View not found for TimeSeriesViewModel" – Joe

+0

Das TimeSpaceViewModel muss irgendwo herkommen, das ist was ich mit dem Import gemeint habe ... (Sie haben auf Ihrem Fenstermanager exportieren, also nehme ich an, dass Sie MEF verwenden). –

+0

Ich arbeite an einem Projekt, um es hoffentlich zu vereinfachen: Übersetzungen, Konfiguration, Caliburn.Micro, MahApps, NotifyIcon WPF und MEF. Dies kann hier gefunden werden: https://github.com/dapplo/Dapplo.CaliburnMicro und hat ein Demo-Projekt, wo ich einen Dialog hinzugefügt habe. –

0

Für die neuen Caliburn.Micro und relevant für diesen Thread, wenn Sie Caliburn.Micro SimpleContainer in Ihrem AppBootStrapper für eine IoC Dependency-Injektion Container verwenden, dann verwenden Sie nicht MEF oder andere IoC-Container-Implementierung.

Viele alte StackOverflow-Diskussionen und Code im Internet verwenden MEF mit Caliburn.Micro, aber der von Caliburn.Micro bereitgestellte SimpleContainer kann für Ihr Projekt ausreichend sein (wenn ja, lassen Sie sich durch den MEF-Code nicht verwirren wenn man Beispiele betrachtet).

Calburn.Micro Wiki entry for SimpleContainer.