2016-07-26 33 views
0

Gibt es eine intelligente Möglichkeit für mich herauszufinden, was WPF-Fenster mit welchem ​​ViewModel verknüpft ist?Fenster suchen, das einem ViewModel in WPF und MVVM/MVVMLight zugeordnet ist

Ich baue gerade einen Dialog-Service und ich muss den Besitzer auf ein bestimmtes Fenster einstellen. Ich bin gerade dabei, die .Owner Eigenschaft auf Application.Current.MainWindow hartcoding, aber ich dachte, ich würde hier überprüfen, ob jemand etwas ähnliches getan hatte und hatte eine schlau davon, dies zu tun.

Ein Weg wäre, den Typ Window dem ViewModel in einem Wörterbuch zuzuordnen, das das ViewModel als Schlüssel in meinem ViewModelLocator verwendet, wenn es initialisiert wird? Aber was dann?

meine MainViewModel Unter der Annahme, nennt den folgenden Code

_dialogService.ShowDialog(settingsWindowViewModel); 

ich eine der Eigenschaften meiner SettingsWindowViewModel als solche weitergeben möchte:

SettingsWindowViewModel settingsWindowViewModel = new SettingsWindowViewModel 
{ 
    Title = "Settings", 
    Owner = "MainViewModel" or //this; 
} 

und in der Definition des DialogService, die ShowDialog würde so definiert werden:

public bool? ShowDialog(IDialogWindowViewModel dialogViewModel) 
{ 
    var win = new WindowDialog 
    { 
     Title = dialogViewModel.Title, 
     Owner = GetWindowByViewModel(dialogViewModel.Owner); 
    } 
} 

Wo das GetWindowByViewModel auf das Wörterbuch zugreifen wird, das die Fenstertypen enthält, aber ich bin nicht sicher, wie das tatsächliche Fenster abgerufen wird, da ich nur den "Typ" habe.

Wo Besitzer ist das ViewModel mit einem bestimmten Fenstertyp zugeordnet.

Ich habe etwas ähnliches wie die oben in einem Projekt gesehen, das Unity wurde mit, aber a) Ich kann mich nicht erinnern, wo ich das sah, und b) Ich verwende MVVMLight statt Unity.

Irgendwelche Vorschläge zur Handhabung eines solchen Szenarios?

Antwort

0

Ich endete mit meinem eigenen Vorschlag.

Hier ist der Zusammenbruch:

  1. ein Wörterbuch der zum ViewModelLocator Fügen Sie den Ansichtsmodell-Typen und den Fenstertyp zu speichern.

    public static Dictionary<Type, Type> WindowTypes; 
    

    Hinweis: Stellen Sie sicher, dass der ViewModelLocator auf die gesamte App verfügbar ist, ein öffentliches statisches Feld in der ViewModelLocator Klasse definieren.

    öffentliche statische ViewModelLocator-Instanz => Application.Current.Resources ["Locator"] als ViewModelLocator;

  2. In den Fenstertyp und Ansichtsmodell Typ den WindowsTypes oben in jedem Windows definiert Wörterbuch, das ein Dialogfeld anzuzeigen erfordert und dass müssen als übergeordnete Fenster handeln.

    public MainWindow() 
    { 
        InitializeComponent(); 
        this.Loaded += (s, e) => 
        { 
         // register window type to corresponding viewmodel 
         ViewModelLocator.WindowTypes.Add(this.DataContext.GetType(), 
         typeof(this.GetType()); 
        }; 
    } 
    

    HINWEIS: Die Verwendung von 'this.DataContext.GetType()‘wird immer in meinem Szenario arbeiten, wie ich bin definieren alle meine Viewmodels in XAML:

    DataContext="{Binding Source={StaticResource Locator}, 
    Path=MainWindowViewModel}" 
    
  3. Schließlich gibt es noch die DialogService Definition:

    public bool? ShowDialog(IDialogWindowViewModel dialogViewModel, object parent) 
    { 
        var win = new WindowDialog 
        { 
         Title = dialogViewModel.Title, 
         BtnAccept = {Content = dialogViewModel.AcceptButtonText, 
         Command = dialogViewModel.AcceptButtonCommand}, 
         BtnCancel = {Content = dialogViewModel.CancelButtonText, 
         Command = dialogViewModel.CancelButtonCommand}, 
         SizeToContent = dialogViewModel.SizeToContent, 
         Width = dialogViewModel.Width, 
         Height = dialogViewModel.Height, 
         WindowStartupLocation = dialogViewModel.WindowStartupLocation, 
         DataContext = dialogViewModel, 
         Owner = GetWindowByType(parent.GetType()) 
        }; 
        return win.ShowDialog(); 
    } 
    

Wie Sie sehen können wird der parent Parametertyp verwendet werden, um das entsprechende Fenster zu identifizieren, die in der GetWindowByType Funktion erfolgt:

private Window GetWindowByType(Type type) 
{ 
    if (ViewModelLocator.WindowTypes.ContainsKey(type)) 
    { 
     return Application.Current.Windows.Cast<Window>().FirstOrDefault 
     (window => window.GetType() == ViewModelLocator.WindowTypes 
     [type]) ?? App.Current.MainWindow; 
    } 
    else 
    { 
     return App.Current.MainWindow; 
    } 
} 

ANMERKUNG: Wenn Sie den relevanten ViewModel-Typ im Dictionary nicht finden oder wenn das relevante Fenster beim Durchlaufen aller verfügbaren Windows in der WPF-App ausfällt, wird das Fail-safe-Fenster möglicherweise angezeigt .

Hoffe, das hilft.