【问题标题】:How to make my WPF MainWindow a singleton?如何使我的 WPF MainWindow 成为单例?
【发布时间】:2010-09-30 03:58:33
【问题描述】:

我想让我的 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 应用程序中做过很多次。

【问题讨论】:

    标签: wpf singleton mainwindow


    【解决方案1】:

    不确定是否要使其成为单例,但您为什么要这样做?您可以简单地使用 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 为什么要麻烦..

    【讨论】:

    • 其他部分代码doint this Winow1 = new Window1() ,它会创建另一个实例。
    • Mnl.是的,我知道我可以做到,但我只是想让我的生活更轻松一些。所以,我想调用 MainWindow.Instance.DoSomething() 而不是 ((MainWindow)Application.Current.MainWindow).DoSomething()。
    • 明白,在这种情况下,如上所述保存静态引用应该会让您的生活更轻松。
    【解决方案2】:

    要使MainWindow 成为单例,您需要执行以下步骤: 将MainWindow Instance 添加到MainWindow 类...

    public static MainWindow Instance { get; private set; }
    

    注意:set 访问器是私有的,所以没有人可以将它设置为其他任何东西。

    MainWindow中添加一个静态构造函数,使MainWindow的构造函数private,像这样……

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

    现在从您的App.xaml 文件中删除StartupUri="MainWindow.xaml",以便在您启动应用程序时不会启动默认窗口。在 App.xaml.cs 中捕获 App 类的 Startup 事件,如下所示:

    public App()
    {
        ...
        Startup += App_Startup;
        ...
    }
    
    void App_Startup(object sender, StartupEventArgs e)
    {
        TestApp.MainWindow.Instance.Show();
    }
    

    【讨论】:

    • 您必须在静态构造函数中执行此操作,或者在 Instance getter 中懒惰地执行此操作。此外,对于单例,您通常将构造函数设为私有。在您的示例中,消费者可以创建多个 MainWindow 实例,最后一个将分配给 Instance
    • 至少如果你想正确实现单例模式。这段代码显然可以在其他类可以从Instance 属性访问主窗口的意义上工作,但它不是“纯”单例恕我直言
    【解决方案3】:

    从您的 App.xaml 文件中删除 StartupUri="MainWindow.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>
    

    将处理程序添加到 App.xaml.csApp 类的 Startup 事件。
    在这个处理程序中调用你的单例实例的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 类前面加上了命名空间!

    【讨论】:

      【解决方案4】:

      非常感谢大家的快速解答。关键是我必须从 App.xaml 中删除 StartupUri="MainWindow.xaml"。也感谢静态构造器的提示。还有一点我想说的是,我们也可以重写 OnStartup 来启动主窗口(只是为了缩短几行):

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-04
        • 2021-04-28
        相关资源
        最近更新 更多