如何只允许一个继承窗口的一个实例打开?

时间:2014-01-16 22:15:45

标签: c# wpf inheritance singleton

我已经在WPF工作了一段时间,而且我很难强制从我的MainWindow打开一个窗口的一个实例。我一直试图找出我选择的解决方案是否是最好的解决方案,但这个问题的方式似乎并不多。让我想知道我是否完全以错误的方式解决这个问题。

我试图解决的原始问题只允许打开一个窗口实例,这是我使用单例模型完成的。它最终工作得很好,但我想打开两个窗口,我想要这个功能。我认为让“BaseWindow”继承是很好的,所以我只需要实现一次。那就是我被困住的地方。

我创建了一个非常简单的项目,我试图实现这个想法,但是我在AboutWindow的公共构造函数中遇到了保护级错误,因为WindowBase构造函数是私有的。将它更改为public允许程序编译,但它似乎“跳过”具有“InitializeComponent”的AboutWindow构造函数。

然而,作为旁注,只允许一个实例的部分确实有效。如果我可以使用IniliatizeCompotent的构造函数来工作,我将被设置。为了澄清,任何从WindowBase派生的窗口都可以同时打开。所以在这种情况下,一次只有一个OptionWindow和一个AboutWindow。

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="181" Width="259">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File"></MenuItem>
            <MenuItem Header="_Tools">
                <MenuItem Header="_Options" ></MenuItem>
            </MenuItem>
            <MenuItem Header="_Help">
                <MenuItem Header="_About" Click="AboutMenuItem_Click"></MenuItem>
            </MenuItem>
        </Menu>
        <Grid>
            <TextBlock Text="Content would go here"></TextBlock>
        </Grid>
    </DockPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows;

namespace WpfApplication1 {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }

        private void AboutMenuItem_Click(object sender, RoutedEventArgs e) {
            AboutWindow.Instance.Show();
        }
    }
}

AboutWindow.xaml:

<src:WindowBase x:Class="WpfApplication1.AboutWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:WpfApplication1"
        Title="AboutWindow" Height="300" Width="300">
    <Grid>
        <Label Content="Label" HorizontalAlignment="Left" Margin="84,74,0,0" VerticalAlignment="Top"/>
    </Grid>
</src:WindowBase>

AboutWindow.xaml.cs:

namespace WpfApplication1 {
    /// <summary>
    /// Interaction logic for AboutWindow.xaml
    /// </summary>
    public partial class AboutWindow : WindowBase {
        public AboutWindow() {
            InitializeComponent();
        }
    }
}

WindowBase.cs:

using System;
using System.Windows;

namespace WpfApplication1 {
    public partial class WindowBase : Window {
        private static WindowBase instance;

        static WindowBase() {

        }

        private WindowBase() {
            Closed += AbstractWindow_Closed;
        }

        public static WindowBase Instance {
            get {
                if (instance == null) {
                    instance = new WindowBase();
                } return instance;
            }
        }

        private void AbstractWindow_Closed(object sender, EventArgs e) {
            instance = null;
        }
    }
}

这个拼图的缺失究竟是什么,或者我是以错误的方式解决这个问题的?

2 个答案:

答案 0 :(得分:1)

MainWindow上使用Singleton模式很好,但正如@elgonzo所说,Instance类中继承自AboutWindow类的WindowBase属性返回WindowBase的实例。

此外,任何派生类在初始化时都会自动调用基类构造函数,但是AboutWindow构造函数是publicpublic构造函数不能从private构造函数调用基类。

我不知道您为什么要这样做而不是简单地重复AboutWindow类中的Singleton模式。如果情况是你只想让一个窗口打开,无论哪个窗口都是,那么你将不得不使用不同的方法...有一个非常简单的解决方案,你可以找到它详细信息请参见StackOverflow上的How can I make sure only one WPF Window is open at a time?帖子。

答案 1 :(得分:0)

我不知道您是否需要在Window打开时访问MainWindow,但您可以使用ShowDialog()代替Show()。 然后,您无法访问基础窗口,也无法通过单击任何内容打开另一个窗口。