2014-01-16 27 views
0

我一直在使用WPF一段时间,并且遇到了困难,只能从我的MainWindow强制打开一个窗口的一个实例。我一直在试图找出我选择的解决方案是否是最好的解决方案,但似乎并没有太多关于这个问题的方法。让我想知道我是否完全错误地做了这件事。你如何只允许一个继承窗口的实例打开?

我试图解决的原始问题只允许打开一个窗口的一个实例,我使用单例模型来完成。它结束了工作很好,但我有两个窗口我想打开,我想这个功能。我认为这将是一个很好的做一个“BaseWindow”继承,所以我只需要实现这一次。那就是我陷入困境的地方。

我已经创建了一个非常简单的项目,我试图实现这个想法,但是由于WindowBase构造函数是私有的,所以我在AboutWindow的公共构造函数中遇到了保护级错误。将它更改为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; 
     } 
    } 
} 

恰恰是缺少一块拼图或我要对这个错误的方式是什么?

+0

你的问题是WindowBase中的Instance属性创建一个WindowBase对象,而不是一个AboutWindow对象。 – elgonzo

+0

首先,用以下信息更新你的问题:假设你有两个窗口类型A和B,它们都来自WindowBase。现在,您是想要只打开一个A还是只打开一个B,还是可以同时打开一个窗口A和一个窗口B? – elgonzo

+0

更新了我的问题。我正在寻找后者,同时开放一个窗口A和一个窗口B.在这种情况下,一个OptionWindow和一个AboutWindow。 – Rakshasas

回答

1

使用Singleton模式上MainWindow是好的,但作为@elgonzo说,你已经从WindowBase类继承的AboutWindow类的Instance属性返回WindowBase一个实例。

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

我不知道你为什么要这样做,而不是简单地重复AboutWindow类中的Singleton模式。如果情况是你只想让一个窗口打开,不管那个窗口是什么,那么你将不得不使用不同的方法......这个要求有一个非常简单的解决方案,你可以在StackOverflow的How can I make sure only one WPF Window is open at a time?这篇文章中找到它。

+0

我确实理解构造函数的概念,但我对我能做些什么感到茫然。至于重复Singleton模式,我绝对可以,但我正试图成为一个更有知识的程序员,并且一直在寻找更好的方法。不,我不想只允许一个窗口打开,只是一个特定类型的窗口。我不特别在乎是否有人打开实际应用程序的6个实例,但只有一个“AboutWindow”或一个“OptionWindow”。但是,AboutWindow和OptionWindow可能同时打开。 – Rakshasas

+0

@Rakshasas,重复单身模式是要走的路。无论您尝试什么,它都不会像“AboutWindow.Instance”或“OtherWindow.Instance”那样易读。你可以尝试实现类似* WindowBase.GetInstance ()*,但只是比较它的丑陋外观和简洁的* AboutWindow.Instance *。 (如果你想有很多类型的singleton模式,像Factory.GetSingletonInstance ()可能是要走的路,尽管...) – elgonzo

+0

好的。那么我会屈服于专家。我想有一个问题很好,基本上发现你在正确的轨道上。谢谢你们俩。 – Rakshasas

0

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

+0

对不起,但这是一个可怕的想法,显然*不是*作者所要求的问题。如果你编辑你的答案并加以改进,我会很乐意删除这个投票。但是,我不确定如何从您拥有的东西开始改进它。 – Sheridan

+0

我可以使用ShowDialog(),但我绝对讨厌它。我发现它通常会限制应用程序的可用性。有时候有一个目的,但我不想在这种情况下拿走使用主窗口的能力。 – Rakshasas