2010-09-30 14 views
5

Voglio rendere il mio MainWindow un singleton perché voglio rendere più facile l'accesso da tutte le altre finestre della mia app. Ma non potevo farcela. Ecco cosa ho fatto.Come rendere la mia WPF MainWindow un singleton?

Come al solito, ho reso privato l'appaltatore MainWindow e creato una proprietà public static MainWindow Instance per restituire un'istanza statica. Quando l'ho eseguito senza altre modifiche, ho ricevuto l'errore "Nessuna fonte disponibile". Ho cercato su Internet e ho trovato un argomento correlato a http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. Tuttavia, non ho potuto farlo funzionare come suggerito lì. Alcuni suggeriscono di fare un cambiamento in MainWindow.xaml da

<Window x:Class="TestApp.MainWindow" 

a

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

che sembra logico. Tuttavia, quando ho fatto questo, ho ricevuto un sacco di errori di compilazione (il primo dice che lo spazio dei nomi TestApp contiene già una definizione di 'MainWindow').

Ho trovato molti articoli su Internet su come creare un'app di istanza singola. Non sto cercando questo. Voglio solo rendere la mia MainWindow un singleton. L'ho fatto nelle app WinForm molte volte.

risposta

11

per rendere il MainWindow un Singleton, questi sono i passi necessari da fare: Aggiungere un MainWindowInstance-MainWindow classe ...

public static MainWindow Instance { get; private set; } 

Nota: accesso set è privato in modo che nessun altro può impostare a qualsiasi altra cosa.

Aggiungi un costruttore statico in MainWindow e fare il costruttore di MainWindowprivate, come questo ...

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

private MainWindow() 
{ 
    InitializeComponent(); 
} 

Ora rimuovere StartupUri="MainWindow.xaml" dal file App.xaml in modo che nessuna finestra di default viene avviato quando si avvia l'applicazione. Prendere l'evento di avvio della classe App in App.xaml.cs come questo:

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

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

Devi farlo in un costruttore statico o pigramente nel getter 'Instance'. Inoltre, per singleton di solito rendi privati ​​i costruttori. Nel tuo esempio, i consumatori possono creare più istanze di MainWindow e l'ultima sarà assegnata a 'Instance' –

+0

Almeno se si desidera implementare correttamente il modello singleton. Questo codice funzionerà ovviamente nel senso che altre classi possono accedere alla finestra principale dalla proprietà 'Instance', ma non è" puro "singleton IMHO –

+0

Sì, sono d'accordo. Vedi il codice modificato. – Yogesh

12

Non sono sicuro di renderlo singleton, ma perché vorresti? È semplice utilizzare Application.Current.MainWindow per ottenere la proprietà Application.MainWindow in qualsiasi momento da qualsiasi punto dell'applicazione. Vedere: http://msdn.microsoft.com/en-us/library/system.windows.application.mainwindow(v=VS.90).aspx.

Window mainWin = Application.Current.MainWindow; 
mainWin.Title = "This will be set as the title of the Main Window"; 

Rendere il singolo ancora non ha senso per me - in che modo lo rende più accessibile? È sempre possibile salvare riferimento alla vostra finestra principale in una variabile statica pubblica - questo potrebbe essere impostato nel costruttore della finestra principale:

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; 
    } 
} 

Ma poi dato l'Application.Current.MainWindow sopra perché preoccuparsi ..

+0

Che dire altra parte del codice doint questo Winow1 = new Window1(), è creerà un'altra istanza. – TalentTuner

+0

Mnl. Sì, so che posso farlo, ma voglio solo rendere la mia vita un po 'più facile. Quindi, voglio chiamare MainWindow.Instance.DoSomething() invece di ((MainWindow) Application.Current.MainWindow) .DoSomething(). – newman

+0

Capito, in tal caso, salvare un riferimento statico come sopra dovrebbe semplificarti la vita. – markmnl

4

Rimuovi StartupUri="MainWindow.xaml" dal file App.xaml. WPF non avvierà più alcuna finestra per te.

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

aggiungere un gestore per l'evento Startup della classe App in App.xaml.cs.
In questo gestore chiamare il metodo Show() dell'istanza singleton.

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(); 
     } 
    } 
} 

Nota: La classeApp ha una proprietà chiamata MainWindow, quindi in App_Startup() ho prefissato classe MainWindow con lo spazio dei nomi!

0

Grazie a tutti voi per i answsers veloci. Il punto chiave è che devo rimuovere StartupUri="MainWindow.xaml" da App.xaml. Grazie anche per la punta del contructor statico. Un altro punto che vorrei menzionare è che possiamo anche ignorare OnStartup per l'avvio della finestra principale (solo per fare un paio di linee più corte):

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