Wie bekomme ich eine statische Referenz auf ein WPF-Fenster?

7

Ich habe eine Menge Möglichkeiten ausprobiert, um eine statische Referenz meines Fensters über mein Programm zu erhalten. Ich muss auf alle seine Mitglieder zur Laufzeit von verschiedenen Klassen zugreifen, so dass eine statische Referenz benötigt wird.

Was ich gerne hätte, wäre etwas wie Program.Window1 , wobei Core statisch ist und MyWindow eines seiner statischen Mitglieder ist.

In WinForms deklariere ich normalerweise mein statisches Formular in Program.cs, aber das scheint nicht mit WPF und ihrer benutzerdefinierten "App.xaml" ApplicationDefinition zu funktionieren.

Wie kann ich es tun?

Hinweis: Ich habe bereits eine Reihe von Möglichkeiten ausprobiert: Einen direkten Aufruf eines neuen Fensters zu verwenden (d. h. Program.Window1 = new Window1() ) funktioniert nicht, da ich eine Thread-Invaliditäts-Ausnahme erhalte. Wie ich bisher verstanden habe, kann nur ApplicationDefinitions Windows in WPF starten.

Hier ist die Ausnahme, wenn ich versuche, ein Fenster "nach Code" zu erstellen und nicht nach dem StartupUri der XAML ApplicationDefinition:

  

Der aufrufende Thread muss STA sein, da viele UI-Komponenten dies erfordern.

    
Lazlo 13.02.2010, 21:43
quelle

4 Antworten

10

Erstellen Sie eine statische Klasse, die das Fensterobjekt enthalten kann, und wenn das Fenster erstellt wird, übergibt es sich selbst an die statische Klasse. Von da an kann die statische Klasse das Fensterobjekt an interessierte Parteien übergeben, obwohl das Fenster angezeigt wird Objekt selbst ist nicht statisch. Etwas wie das. Ihr Formular muss nicht statisch sein, Sie brauchen nur einen statischen Platz, um das Formularobjekt zu halten.

%Vor%     
John Knoeller 13.02.2010, 21:54
quelle
5

Versuchen Sie Folgendes ((MainWindow) App.Current.Windows [0]). MainCanvas.

    
Academy of Programmer 31.10.2011 16:55
quelle
4

Es ist absolut möglich, eigene Fenster mit WPF zu instanziieren. Aber ja, Sie müssten auf dem "UI-Thread" sein (was ein STA-Thread ist).

Sagen wir beispielsweise, dass wir eine Eigenschaft in unserer App-Klasse haben möchten, die ein Fenster freilegt.

%Vor%

Das Problem mit diesem Code ist, wie Sie erfahren haben, abhängig davon, welcher Thread den MyWindow-Getter aufruft, new Window1() wird fehlschlagen, wenn der Thread keine STA ist.

Um sicherzustellen, dass das Fenster im rechten Thread erstellt wird, geben Sie das Dispatcher-Objekt . Dieses Objekt wird in WPF verwendet, um sicherzustellen, dass die Kommunikation zwischen UI-Elementen im richtigen Thread erfolgt.

Zurück zu unserem new Window1 , können wir das App.Dispatcher-Objekt verwenden, um sicherzustellen, dass die Operation new im Hauptanwendungs-Thread wie folgt ausgeführt wird:

%Vor%

Hier halte ich das Dispatcher-Objekt der aktuellen Anwendung fest und rufe Invoke mit einem Delegaten auf, der den eigentlichen Neustart durchführt. Invoke stellt sicher, dass mein Delegat im richtigen Thread ausgeführt wird, und gibt das Ergebnis zurück. Voila, das Fenster wird ohne den gefürchteten STA-Fehler erstellt.

Nun müssen Sie daran denken, dass weitere Aufrufe der MyWindow-Instanz auch für den richtigen Thread ausgeführt werden müssen. Um zu vermeiden, dass Ihr Code mit Aufrufen von Dispatcher.Invoke verschmutzt wird, könnte es nützlich sein, die Fensterinstanz hinter einer einfachen API zu verpacken. Z.B. Eine Show-Methode könnte so implementiert werden, dass der Show-Aufruf über das Dispatcher-Objekt des Fensters verwaltet wird:

%Vor%     
Peter Lillevold 13.02.2010 23:49
quelle
2

Ich habe das mit Erfolg benutzt. Deklarieren Sie eine statische Variable des Fenstertyps. Setzen Sie dann im Konstruktor des Fensters die statische Variable auf "this". Ich habe es in der ganzen App verwendet und es scheint gut zu funktionieren innerhalb von statischen oder Instanzmethoden.

%Vor%

Zum Beispiel kann ich das machen.

%Vor%     
howserss 09.12.2014 15:32
quelle

Tags und Links