2017-06-29 1 views
0

Ich schreibe eine WPF-Anwendung und versuche, effektive MVVM-Praktiken zu lernen. Ich habe MenuItem-Schaltflächen in meiner Schnittstelle (in MainWindow.xaml) und möchte ihre Command-Eigenschaft an einen ICommand binden, den ich erstellt habe.Wie kann ich Application-Scope-Variable erstellen, die an beliebiger Stelle in der Anwendung gesetzt/abgerufen werden kann? (WPF/MVVM)

Wenn die Anwendung startet, möchte ich ein Bool (das von einer beliebigen Stelle in der Anwendung gesetzt/erhalten werden kann) auf ursprünglich auf false gesetzt werden. Wenn das MenuItem "File> New" aktiviert ist, möchte ich den Befehl auslösen und gegen die Application-Scope-Variable in seiner "CanExecute" -Methode überprüfen, die dann das MenuItem aktivieren oder deaktivieren soll.

Mein Problem ist, dass ich nicht herausfinden kann, wo genau ist der beste Ort zum Speichern/Instanziieren/etc diese Variable (oder Eigenschaft?).

Ich habe eine Vielzahl verschiedener Kombinationen ausprobiert, einschließlich der Implementierung eines Singleton-Pattern-Designs mit meiner Klasse "Workspace" (die die boolesche Variable enthält), und ich bastle jetzt an statischen Klassen und Variablen.

Mein Code wird hier gezeigt:

XAML:

<MenuItem Header="_File"> 
      <MenuItem Header="_New Project" Command="{Binding NewProjectCommand, Source={StaticResource project}}"/> 
      <MenuItem Header="_Open Project"/> 
</MenuItem> 

App.xaml.cs:

public WorkspaceViewModel WorkspaceInfo { get; set; } 

public partial class App : Application 
{ 
    public App() 
    { 
     //Store variable here? How? And what is the best way to expose it to my Commands? 
    } 

} 

WorkspaceViewModel.cs:

class WorkspaceViewModel : Workspace 
{ 

} 

NewProjectCommand.cs:

class NewProjectCommand : ICommand 
{ 

    public NewProjectCommand(ProjectViewModel projectViewModel) 
    { 
    } 

    public event EventHandler CanExecuteChanged; 

    public bool CanExecute(object parameter) 
    { 
     //Do an evaluation here using the new bool in App.xaml.cs 
     //return true/false, based on the evaluation 

    } 

    public void Execute(object parameter) 
    { 
     //Perform steps here to switch the bool in App.xaml.cs, and perform other command functionality 
    } 
} 

Workspace.cs:

class Workspace : INotifyPropertyChanged 
{ 
    private bool _isProjectOpen; 

    public bool IsProjectOpen 
    { 
     get { return _isProjectOpen; } 
     set 
     { 
      _isProjectOpen = value; 
      OnPropertyChanged(); 
     } 
    } 


    #region INotifyPropertyChanged members 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged([CallerMemberName] string propertyName = "") 
    { 
     var handler = PropertyChanged; 

     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 
} 

ich im Grunde ein Wahr/Falsch-Wert in dem höchsten Niveau meiner Anwendung speichern bin zu wollen, Auf diese Weise kann ich die Variable in "CanExecute" holen und die Variable in den "Execute" Methoden für alle meine ICommands setzen, so dass alle meine MenuItems aktiviert und deaktiviert werden angemessene Zeit.

Ich weiß, dass dies eine ziemlich langatmige Frage ist, aber jede Hilfe wird sehr geschätzt und wenn ich weitere Informationen posten muss, würde ich mich freuen, dies zu tun!

Vielen Dank im Voraus!

+1

Was war falsch "kann von überall in der Anwendung eingestellt/get werden"? –

+0

Wie die verschiedenen Antworten beschreiben, gibt es viele Möglichkeiten, dies zu tun. Wenn Sie Best Practices für MVVM lernen, empfehle ich, diese Variable in ein Modell/einen Service zu stellen, der den Anwendungsstatus speichert und seine Schnittstelle in alle ViewModels einfügt, die über den Anwendungsstatus Bescheid wissen müssen. Auf diese Weise wird die Testbarkeit Ihrer ViewModels nicht beeinträchtigt. –

+0

Die ganze Zeit, als ich über meine möglichen Optionen nachdachte, hoffte ich wirklich, dass es eine einfache Lösung gab, mit der ich gehen konnte. Ich lehnte mich an eine leicht zugängliche Eigenschaft im Gegensatz zu einem Singleton, obwohl ich hoffentlich in der Lage sein werde zu lernen, wie man es schließlich benutzt. Vielen Dank! –

Antwort

2

Ein „-Anwendung-scope Variable“ zu laden, kann als Eigenschaft in der App-Klasse deklariert werden:

public partial class App : Application 
{ 
    public bool YourProperty { get; set; } // is false by default 
} 

Nun ist die Eigenschaft von

((App)Application.Current).YourProperty = true; 

und

mit dem Singleton
var propertyValue = ((App)Application.Current).YourProperty; 
+0

Das ist perfekt - genau das, was ich brauchte. Ich denke, mein Problem war eine Kombination aus der Tatsache, dass ich die Eigenschaft nicht an erster Stelle korrekt genannt habe, um sie setzen zu können. Und darüber hinaus wurde mein MenuItem.IsEnabled nicht richtig aktualisiert, weil ich in meiner "CanExecuteChanged" -Methode meines Befehls nichts hatte! –

3

Shop der Wert im Properties Wörterbuch der statischen Application.Current Beispiel:

Application.Current.Properties["NameOfProperty"] = false; 
var myProperty = (bool)Application.Current.Properties["NameOfProperty"]; 
+1

Nachdem ich das versucht habe, hat es auch funktioniert und ich kann Anwendungen anderswo in meiner Anwendung sehen, danke! –

1

Zwei Wege
1.] Entweder sie speichern als Projekteinstellungen
Rechts auf Projekt klicken als auf Eigenschaften und als gehe zu den Einstellungen
Erstelle deine Einstellungen hier.
enter image description here Sie können sie zugreifen oder sie manipulieren programmatisch in Ihrem Code

Properties.Settings.Default.SavedInputString 

2.] Bewahren Sie sie in benutzerdefinierte XML-Datei
XML-Dateien sind einfach zu erstellen, zu lesen und zu aktualisieren und es ist ein schneller Weg, Einstellung zur Laufzeit

+0

OP möchte anscheinend nicht den Eigenschaftswert speichern und neu laden. – Clemens

+0

Beide Optionen, die Sie vorschlagen, sind sehr nützlich für andere Mechanismen in meiner Anwendung, also werde ich definitiv benutzerdefinierte Einstellungen in den Einstellungen speichern. Und ich benutze die Anwendung tatsächlich, um von Benutzern eingegebene Daten in eine XML-Datei zu schreiben, also werde ich bald an diesem Teil arbeiten. Ich habe über meine verschiedenen Möglichkeiten nachgedacht und das wird eine meiner nächsten Hürden sein. Haha –

Verwandte Themen