2014-01-16 28 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