Как сделать мой 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
один шаг, это шаги, которые вам нужно сделать: Добавить MainWindow
Instance
в MainWindow
учебный класс...
public static MainWindow Instance { get; private set; }
Примечание: set accessor является приватным, так что никто другой не может установить его на что-либо другое.
Добавить статический конструктор в MainWindow
и сделать конструктор MainWindow
private
, как это...
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();
}
}