How to make my WPF MainWindow a singleton?

旧巷老猫 提交于 2019-11-27 04:27:06

问题


I want to make my MainWindow a singleton because I want to make accessing it from all other windows in my app easier. But I couldn't make it run. Here is what I did.

As usual, I made the MainWindow contractor private, and created a public static MainWindow Instance property to return a static instance. When I just run it without any other changes, I got "No Source Available" error. I googled the Internet and found one related topic at http://www.netframeworkdev.com/windows-presentation-foundation-wpf/xamlc-singleton-class-80578.shtml. However, I couldn't make it work as suggested there. Some suggest to make a change in MainWindow.xaml from

<Window x:Class="TestApp.MainWindow"

to

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

Which looks logical. However, when I did this, I got tons of compiling errors (first one says the namespace TestApp already contains a definition of 'MainWindow'.)

I found many articles on the Internet about how to make single instance app. I'm not looking for this. I just want to make my MainWindow a singleton. I have done it in WinForm apps many times.


回答1:


To make the MainWindow a singleton, these are the steps you need to make: Add a MainWindow Instance to MainWindow class...

public static MainWindow Instance { get; private set; }

Note: set accessor is private so that nobody else can set it to anything else.

Add a static constructor in MainWindow and make the constructor of MainWindow private, like this...

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

private MainWindow()
{
    InitializeComponent();
}

Now remove StartupUri="MainWindow.xaml" from your App.xaml file so that no default window is launched when you start the application. Catch the Startup event of your App class in App.xaml.cs like this:

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

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



回答2:


Not sure about making it singleton, but why would you want to? You can simple use Application.Current.MainWindow to get the Application.MainWindow property anytime from anywhere in your application.. See: 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";

Making it singleton still does not make sense to me - how does that make it more accessible? You can always save reference to your main window in a public static variable - this could be set in the constructor of your 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;
    }
}

But then given the above Application.Current.MainWindow why bother..




回答3:


Remove StartupUri="MainWindow.xaml" from your App.xaml file. WPF will not launch any window for you anymore.

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

Add a handler to the Startup event of your App class in App.xaml.cs.
In this handler call the Show() method of your singleton instance.

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

Note: The App class has a property called MainWindow, hence in App_Startup() I prefixed the MainWindow class with the namespace!




回答4:


Thank you all very much for the quick answsers. The key point is that I have to remove StartupUri="MainWindow.xaml" from App.xaml. Thanks also for the tip of static contructor. Another point I want to mention is that we can also override OnStartup to startup the main window (just to make a few lines shorter):

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


来源:https://stackoverflow.com/questions/3827612/how-to-make-my-wpf-mainwindow-a-singleton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!