2010-09-30 6 views
5

Ich möchte meine MainWindow zu einem Singleton machen, weil ich den Zugriff von allen anderen Fenstern in meiner App aus erleichtern möchte. Aber ich konnte es nicht laufen lassen. Hier ist was ich getan habe.Wie mache ich mein WPF MainWindow zu einem Singleton?

Wie üblich, habe ich den MainWindow-Subunternehmer privat gemacht und eine public static MainWindow Instance-Eigenschaft erstellt, um eine statische Instanz zurückzugeben. Wenn ich es ohne weitere Änderungen ausführte, bekam ich den Fehler "Keine Quelle verfügbar". Ich googelte das Internet und fand ein verwandtes Thema unter http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. Ich konnte es jedoch nicht so machen, wie es dort vorgeschlagen wurde. Einige schlagen vor, eine Änderung in MainWindow.xaml von

<Window x:Class="TestApp.MainWindow" 

zu

<Window x:Class="TestApp.MainWindow.Instance" 

zu machen, die logisch aussieht. Jedoch, als ich dies tat, bekam ich Tonnen von Kompilierungsfehlern (das erste besagt, dass der Namespace TestApp bereits eine Definition von 'MainWindow' enthält.)

Ich fand viele Artikel im Internet darüber, wie Einzelinstanz-App zu machen. Ich suche das nicht. Ich möchte nur meine MainWindow zu einem Singleton machen. Ich habe es oft in WinForm-Apps gemacht.

Antwort

11

Um die MainWindow einen Singleton zu machen, das sind die Schritte, die Sie machen müssen: eine MainWindowInstance-MainWindow Klasse hinzufügen ...

public static MainWindow Instance { get; private set; } 

Hinweis: set-Accessor so dass niemand sonst privat einstellen zu allem anderen.

einen statischen Konstruktor in MainWindow hinzufügen und den Konstruktor von MainWindowprivate, wie diese machen ...

static MainWindow() 
{ 
    Instance = new MainWindow(); 
} 

private MainWindow() 
{ 
    InitializeComponent(); 
} 

Jetzt StartupUri="MainWindow.xaml" aus Ihrer App.xaml Datei entfernen, so dass kein Standardfenster gestartet wird, wenn Sie die Anwendung starten. Fangen Sie die Startup-Ereignis Ihrer App-Klasse in App.xaml.cs wie folgt aus:

public App() 
{ 
    ... 
    Startup += App_Startup; 
    ... 
} 

void App_Startup(object sender, StartupEventArgs e) 
{ 
    TestApp.MainWindow.Instance.Show(); 
} 
+0

Sie müssen dies in einem statischen Konstruktor oder faul im 'Instance'-Getter tun. Auch für Singleton machen Sie Konstruktoren normalerweise privat. In Ihrem Beispiel können die Benutzer mehrere MainWindow-Instanzen erstellen, und die letzte Instanz wird "Instance" zugewiesen. –

+0

Zumindest, wenn Sie das Singleton-Muster ordnungsgemäß implementieren möchten. Dieser Code funktioniert natürlich in dem Sinne, dass andere Klassen über die 'Instance'-Eigenschaft auf das Hauptfenster zugreifen können, aber es ist kein" reiner "Singleton. IMHO –

+0

Ja, ich stimme zu. Siehe den geänderten Code. – Yogesh

12

Ich bin mir nicht sicher ob ich Singleton machen kann, aber warum willst du das? Sie können Application.Current.MainWindow einfach verwenden, um die Application.MainWindow-Eigenschaft jederzeit von überall in Ihrer Anwendung abzurufen. Siehe: http://msdn.microsoft.com/en-us/library/system.windows.application.mainwindow(v=VS.90).aspx.

Dass es Singleton macht, macht immer noch keinen Sinn für mich - wie macht es das zugänglicher? Sie können immer Bezug auf Ihre Hauptfenster in einer öffentlichen statischen Variablen speichern - dies im Konstruktor des Hauptfensters gesetzt werden könnte:

public partial class MainWindow : Window 
{ 
    public static MainWindow myMainWindow; // ASSUMPTION: only one MainWindow is ever constructed otherwise this will be overwritten by latest such instance 

    public MainWindow() 
    { 
     InitializeComponent();    
     myMainWindow = this; 
    } 
} 

Aber dann angesichts der oben Application.Current.MainWindow warum .. Mühe

+0

Was ist mit anderem Teil des Codes doint dieser Winow1 = new Window1(), es erstellt eine weitere Instanz. – TalentTuner

+0

Mnl. Ja, ich weiß, dass ich das kann, aber ich möchte einfach mein Leben ein wenig erleichtern. Also möchte ich MainWindow.Instance.DoSomething() anstelle von ((MainWindow) Application.Current.MainWindow) .DoSomething() aufrufen. – newman

+0

Verstanden, in diesem Fall sollte das Speichern einer statischen Referenz wie oben Ihr Leben erleichtern. – markmnl

4

Entfernen Sie StartupUri="MainWindow.xaml" von Ihrer App.xaml Datei. WPF wird kein Fenster mehr für Sie starten.

<Application x:Class="WpfApplication1.App" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
</Application> 

einen Handler zum Startup Ereignis Ihrer App Klasse in App.xaml.cs hinzufügen.
In diesem Handler rufen Sie die Show() Methode Ihrer Singleton-Instanz auf.

using System; 
using System.Windows; 

namespace WpfApplication1 
{ 
    public partial class App : Application 
    { 
     public App() 
     { 
      Startup += new StartupEventHandler(App_Startup); 
     } 

     void App_Startup(object sender, StartupEventArgs e) 
     { 
      WpfApplication1.MainWindow.Instance.Show(); 
     } 
    } 
} 

Hinweis: Die App Klasse hat eine Eigenschaft MainWindow genannt, also in App_Startup() ich die MainWindow Klasse mit der Namespace-Präfix!

0

Vielen Dank sehr viel für die schnellen answsers. Der entscheidende Punkt ist, dass ich StartupUri="MainWindow.xaml" aus App.xaml entfernen muss. Danke auch für die Spitze des statischen Konstruktors. Ein weiterer Punkt, den ich erwähnen möchte, ist, dass wir auch OnStartup außer Kraft setzen können das Hauptfenster beim Start (nur ein paar Zeilen kürzer zu machen):

public partial class App : Application 
    { 
     protected override void OnStartup(StartupEventArgs e) 
     { 
      base.OnStartup(e); 
      TestApp.MainWindow.Instance.Show(); 
     } 
    } 
Verwandte Themen