2010-09-30 2 views
5

Я хочу сделать мой MainWindow синглтон, потому что я хочу сделать доступ к нему из всех других окон в моем приложении проще. Но я не мог заставить его бежать. Вот что я сделал.Как сделать мой WPF MainWindow одиночным?

Как обычно, я сделал основной подрядчик MainWindow и создал свойство public static MainWindow Instance, чтобы вернуть статический экземпляр. Когда я просто запускаю его без каких-либо изменений, я получил ошибку «Нет источника». Я googled в Интернете и нашел одну связанную тему в http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. Однако я не мог заставить его работать, как было предложено. Некоторые предлагают внести изменения в MainWindow.xaml от

<Window x:Class="TestApp.MainWindow" 

в

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

который выглядит логичным. Однако, когда я это сделал, у меня появилось множество компиляционных ошибок (первый говорит, что пространство имен TestApp уже содержит определение «MainWindow».)

Я нашел много статей в Интернете о том, как сделать одно приложение экземпляра. Я не ищу этого. Я просто хочу сделать мой MainWindow синглом. Я делал это в приложениях WinForm много раз.

ответ

11

Чтобы сделать MainWindow синглтона, это шаги, которые необходимо сделать: Добавить MainWindowInstance в MainWindow класс с ...

public static MainWindow Instance { get; private set; } 

Примечание: набор аксессор является частным, так что никто не может установить это ни к чему другому.

Добавить статический конструктор в MainWindow и сделать конструктор MainWindowprivate, как это ...

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

private MainWindow() 
{ 
    InitializeComponent(); 
} 

Теперь удалите StartupUri="MainWindow.xaml" из файла App.xaml так, что окно по умолчанию не запускается при запуске приложения. Поймать событие запуска вашего класса App в App.xaml.cs так:

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

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

Вы должны сделать это в статическом конструкторе или лениво в «экземпляре» getter. Кроме того, для singleton вы обычно делаете конструкторы частными. В вашем примере потребители могут создавать несколько экземпляров MainWindow, а последний будет назначен «Экземпляр» –

+0

По крайней мере, если вы хотите правильно реализовать шаблон singleton. Этот код, очевидно, будет работать в том смысле, что другие классы могут получить доступ к главному окну из свойства 'Instance', но это не« чистый »singleton IMHO –

+0

Да, я согласен. См. Измененный код. – Yogesh

12

Не уверен в том, чтобы сделать его одиночным, но зачем вам это нужно? Вы можете просто использовать Application.Current.MainWindow, чтобы получить свойство Application.MainWindow в любое время из любого места в вашем приложении. См.: 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"; 

Сделать это singleton все еще не имеет смысла для меня - как это делает его более доступным? Вы всегда можете сохранить ссылку на главном окне в общественной статической переменной - это может быть установлен в конструкторе главного окна:

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

Но учитывая выше Application.Current.MainWindow зачем ..

+0

Что о другой части кода doint этого Winow1 = новый window1(), его создаст другой экземпляр. – TalentTuner

+0

Mnl. Да, я знаю, что могу это сделать, но я просто хочу немного облегчить себе жизнь. Поэтому я хочу вызвать MainWindow.Instance.DoSomething() вместо ((MainWindow) Application.Current.MainWindow) .DoSomething(). – newman

+0

Понял, в этом случае сохранение статической ссылки, как указано выше, должно облегчить вашу жизнь. – markmnl

4

Удалить StartupUri="MainWindow.xaml" с вашего App.xaml файл. WPF больше не будет запускать для вас какое-либо окно.

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

Добавление обработчика в Startup случае Вашего App класса в App.xaml.cs.
В этом обработчике вызывается метод Show() вашего экземпляра 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(); 
     } 
    } 
} 

Примечание:App класса имеет свойство MainWindow, следовательно, в App_Startup() я приставку в MainWindow классе с пространством имен!

0

Спасибо всем большое за быстрый answsers. Ключевым моментом является то, что я должен удалить StartupUri="MainWindow.xaml" из App.xaml. Спасибо также за наконечник статического конструктора. Еще один момент, который я хочу отметить, что мы также можем переопределить OnStartup для запуска главного окна (только, чтобы сделать несколько строк короче):

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