2010-09-30 24 views
5

Je veux faire de ma MainWindow un singleton parce que je veux faciliter l'accès à partir de toutes les autres fenêtres de mon application. Mais je ne pouvais pas le faire fonctionner. Voici ce que j'ai fait.Comment rendre mon WPF MainWindow un singleton?

Comme d'habitude, j'ai rendu privé l'entrepreneur MainWindow et j'ai créé une propriété public static MainWindow Instance pour renvoyer une instance statique. Lorsque je l'exécute sans aucun autre changement, j'ai l'erreur "No Source Available". J'ai cherché sur Internet et trouvé un sujet connexe au http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. Cependant, je ne pouvais pas le faire fonctionner comme suggéré ici. Certains suggèrent de faire un changement dans MainWindow.xaml de

<Window x:Class="TestApp.MainWindow" 

à

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

Ce qui semble logique. Cependant, quand j'ai fait cela, j'ai eu des tonnes d'erreurs de compilation (la première dit que l'espace de noms TestApp contient déjà une définition de 'MainWindow'.)

J'ai trouvé de nombreux articles sur Internet sur la façon de créer une application mono-instance. Je ne cherche pas ça. Je veux juste faire de ma MainWindow un singleton. Je l'ai fait dans les applications WinForm plusieurs fois.

Répondre

11

Pour faire la MainWindow un singleton, ce sont les étapes que vous devez faire: Ajouter un MainWindowInstance-MainWindow classe ...

public static MainWindow Instance { get; private set; } 

Note: accesseur set est privé de telle sorte que personne ne peut mettre à tout autre chose.

Ajouter un constructeur statique dans MainWindow et faire le constructeur de MainWindowprivate, comme ça ...

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

private MainWindow() 
{ 
    InitializeComponent(); 
} 

maintenant supprimer StartupUri="MainWindow.xaml" de votre fichier App.xaml de sorte qu'aucune fenêtre par défaut est lancé lorsque vous démarrez l'application. Attrapez l'événement de démarrage de votre classe App dans App.xaml.cs comme ceci:

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

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

Vous devez le faire dans un constructeur statique ou paresseusement dans le getter 'Instance'. De même, pour singleton, vous rendez généralement les constructeurs privés. Dans votre exemple, les consommateurs peuvent créer plusieurs instances de MainWindow et la dernière sera affectée à 'Instance' –

+0

Au moins si vous voulez implémenter correctement le pattern singleton. Ce code fonctionnera évidemment dans le sens où d'autres classes peuvent accéder à la fenêtre principale de la propriété 'Instance', mais ce n'est pas" pur "singleton IMHO –

+0

Oui, je suis d'accord. Voir le code modifié. – Yogesh

12

Je ne suis pas sûr de le rendre unique, mais pourquoi voudriez-vous le faire? Vous pouvez simplement utiliser Application.Current.MainWindow pour obtenir la propriété Application.MainWindow n'importe quand à partir de n'importe où dans votre application. Voir: http://msdn.microsoft.com/en-us/library/system.windows.application.mainwindow(v=VS.90).aspx. Rendre le singleton n'a toujours pas de sens pour moi - comment cela le rend-il plus accessible? Vous pouvez toujours enregistrer référence à votre fenêtre principale dans une variable statique publique - cela pourrait être réglé dans le constructeur de votre fenêtre 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; 
    } 
} 

Mais étant donné la Application.Current.MainWindow ci-dessus .. pourquoi la peine

+0

Qu'en est-il autre partie du Code doint ce Winow1 = new Window1(), il va créer une autre instance. – TalentTuner

+0

Mnl. Oui, je sais que je peux le faire, mais je veux juste rendre ma vie un peu plus facile. Donc, je veux appeler MainWindow.Instance.DoSomething() au lieu de ((MainWindow) Application.Current.MainWindow) .DoSomething(). – newman

+0

Compris, dans ce cas, l'enregistrement d'une référence statique comme ci-dessus devrait vous faciliter la vie. – markmnl

4

Supprimer StartupUri="MainWindow.xaml" de votre fichier App.xaml. WPF ne lancera plus aucune fenêtre pour vous.

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

Ajouter un gestionnaire à l'événement Startup de votre classe App dans App.xaml.cs.
Dans ce gestionnaire, appelez la méthode Show() de votre instance 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(); 
     } 
    } 
} 

Note: La classe App possède une propriété appelée MainWindow, donc dans App_Startup() je préfixés la classe MainWindow avec l'espace de noms!

0

Merci à tous pour les answsers rapides. Le point clé est que je dois supprimer StartupUri="MainWindow.xaml" de App.xaml. Merci aussi pour la pointe du contructeur statique. Un autre point que je voudrais mentionner est que nous pouvons passer outre OnStartup au démarrage de la fenêtre principale (juste pour faire quelques lignes plus courtes):

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