2010-09-30 9 views
5

Chcę, aby mój MainWindow był singletonem, ponieważ chcę, aby dostęp do niego ze wszystkich innych okien w mojej aplikacji był łatwiejszy. Ale nie mogłem go uruchomić. Oto co zrobiłem.Jak uczynić moje WPF MainWindow singleton?

Jak zwykle, wykonałem zlecenie MainWindow jako prywatne i utworzyłem właściwość public static MainWindow Instance, aby zwrócić wystąpienie statyczne. Kiedy po prostu uruchomię go bez żadnych innych zmian, dostaję komunikat "Brak dostępnego źródła". Przeszukałem Internet i znalazłem jeden powiązany temat pod adresem http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. Jednak nie mogłem sprawić, by działało tak, jak to sugerowano. Niektórzy sugerują, aby dokonać zmian w MainWindow.xaml z

<Window x:Class="TestApp.MainWindow" 

do

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

który wygląda logicznie. Jednak kiedy to zrobiłem, mam mnóstwo błędów kompilacji (pierwsza mówi, że przestrzeń testowa Testation zawiera już definicję "MainWindow".)

Znalazłem wiele artykułów w Internecie na temat tworzenia aplikacji pojedynczej instancji. Nie szukam tego. Po prostu chcę, aby mój MainWindow był singletonem. Zrobiłem to wielokrotnie w aplikacjach WinForm.

Odpowiedz

11

Aby dokonać MainWindow pojedyncza, to są kroki, które trzeba zrobić: Dodaj MainWindowInstance do MainWindow klasę ...

public static MainWindow Instance { get; private set; } 

Uwaga: zestaw accessor jest prywatna, tak aby nikt inny nie może ustawić do czegokolwiek innego.

Dodaj statyczny konstruktora w MainWindow i uczynić konstruktora MainWindowprivate, jak to ...

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

private MainWindow() 
{ 
    InitializeComponent(); 
} 

Teraz usunąć StartupUri="MainWindow.xaml" z pliku App.xaml tak, że nie jest uruchomiony domyślny okno po uruchomieniu aplikacji. Połowu zdarzenie Uruchomienie aplikacji w swojej klasie App.xaml.cs tak:

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

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

Musisz to zrobić w statycznym konstruktorze lub leniwie w pobierającym 'Instance'. Ponadto, w przypadku singletonu zazwyczaj tworzysz konstruktorów jako prywatne. W twoim przykładzie konsumenci mogą tworzyć wiele instancji MainWindow, a ostatnia zostanie przypisana do 'Instance' –

+0

Przynajmniej jeśli chcesz poprawnie zaimplementować wzorzec singleton. Kod ten będzie oczywiście działał w tym sensie, że inne klasy mogą uzyskać dostęp do głównego okna z właściwości 'Instance', ale nie jest to" czysty "singleton IMHO –

+0

Tak, zgadzam się. Zobacz zmodyfikowany kod. – Yogesh

12

Nie jesteś pewien, czy to singleton, ale dlaczego chcesz? Możesz łatwo użyć Application.Current.MainWindow, aby uzyskać właściwość Application.MainWindow w dowolnym czasie z dowolnego miejsca w aplikacji. Patrz: 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"; 

Sprawienie, że singleton wciąż nie ma dla mnie sensu - jak to czyni go bardziej dostępnym? Zawsze można zaoszczędzić odniesienie do głównego okna w zmiennej statycznej publicznego - może to być ustawione w konstruktorze głównego okna:

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

Ale biorąc pod uwagę powyższe Application.Current.MainWindow dlaczego przeszkadza ..

+0

co z drugiej strony kodu doint tym Winow1 = new oknie Window1(), to utworzy kolejną instancję. – TalentTuner

+0

Mnl. Tak, wiem, że mogę to zrobić, ale chcę tylko ułatwić sobie życie. Tak więc chcę wywołać MainWindow.Instance.DoSomething() zamiast ((MainWindow) Application.Current.MainWindow) .DoSomething(). – newman

+0

Zrozumiane, w tym przypadku zapisanie statycznego odniesienia jak powyżej powinno ułatwić Ci życie. – markmnl

4

Usuń StartupUri="MainWindow.xaml" ze swojego pliku App.xaml. WPF nie uruchomi już żadnego okna dla ciebie.

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

Dodaj do procedury obsługi zdarzenia Startup swojej klasie App w App.xaml.cs.
W tym podprogramie wywołaj metodę Show() Twojego wystąpienia 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(); 
     } 
    } 
} 

Uwaga: Klasa App ma właściwość o nazwie MainWindow, stąd w App_Startup() ja prefiksem klasę MainWindow z nazw!

0

Dziękuję wszystkim bardzo za szybką answsers. Najważniejsze jest to, że muszę usunąć StartupUri="MainWindow.xaml" z App.xaml. Dziękuję również za wierzchołek statycznego contructora. Kolejnym punktem chcę wspomnieć jest to, że możemy również zastąpić OnStartup uruchomieniem główne okno (tylko do kilku wierszy krótszy):

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