Как сделать мой WPF MainWindow синглтоном?

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

Как обычно, я выделил подрядчика 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 ответа

Решение

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

public static MainWindow Instance { get; private set; }

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

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

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

private MainWindow()
{
    InitializeComponent();
}

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

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

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

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

Удалить 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 класс с пространством имен!

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

 public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            TestApp.MainWindow.Instance.Show();
        }
    }
Другие вопросы по тегам