Как сделать мой WPF MainWindow синглтоном? - PullRequest
5 голосов
/ 30 сентября 2010

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

Как обычно, я сделал подрядчик MainWindow закрытым и создал свойство public static MainWindow Instance для возврата статического экземпляра.Когда я просто запускаю его без каких-либо других изменений, я получаю ошибку «Нет доступного источника».Я погуглил в интернете и нашел одну связанную тему на 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 много раз.

Ответы [ 4 ]

13 голосов
/ 30 сентября 2010

Чтобы сделать MainWindow синглтоном, необходимо выполнить следующие шаги: Добавить MainWindow Instance к MainWindow классу ...

public static MainWindow Instance { get; private set; }

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

Добавьте статический конструктор в MainWindow и сделайте конструктор из MainWindow private, например так ...

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();
}
13 голосов
/ 30 сентября 2010

Не уверен насчет того, чтобы сделать его синглтоном, но зачем вам это? Вы можете просто использовать 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";

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

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, зачем беспокоиться ..

4 голосов
/ 30 сентября 2010

Удалите 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() вашего экземпляра-одиночки.

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 голосов
/ 30 сентября 2010

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

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