如何确保一次只打开一个WPF窗口?

时间:2009-08-26 16:00:22

标签: c# wpf winforms .net-3.5

我有一个WPF窗口,我从winform应用程序内部启动。我只想允许一次打开该WPF窗口的一次实例,并且如果用户试图再次打开它,则不会警告该用户。

我遇到了一个问题,但是尝试搜索正在打开的WPF窗口,因为窗口是从winform启动的。我正常做的是在搜索winform时,我搜索Application.Current.OpenForms中存在的winform的任何实例,并在WPF中搜索Application.Current.Windows

我遇到的问题是,当从winform内部启动时,System.Windows.Application.Current为null,因此我无法以这种方式搜索WPF窗口。有没有更好的方法来搜索打开窗口的现有实例?

我的代码:

if (System.Windows.Application.Current != null)
                {
                    foreach (System.Windows.Window win in System.Windows.Application.Current.Windows)
                    {
                        if (win is frmCaseWpf)
                        {
                            MessageBox.Show("You may have only one active case open at a time.", "Open Case",
                                      MessageBoxButtons.OK,
                                      MessageBoxIcon.Stop);

                            win.WindowState = System.Windows.WindowState.Normal;
                            win.Focus();
                            win.Activate();
                            return;
                        }
                    }
                }

6 个答案:

答案 0 :(得分:6)

您可以使用单个静态变量,而不是搜索静态应用程序对象,而只是在窗口中跟踪它。只需在窗口中保留一个变量:

private static frmCaseWpf openWindow = null; // Assuming your class name is frmCaseWpf

在初始化例程或OnLoaded中创建窗口时,具体取决于您希望它如何工作..:

partial class frmCaseWpf {
    public frmCaseWpf {
         this.OnLoaded += frmCaseWpf_OnLoaded;
    }

    private void frmCaseWpf_OnLoaded(object sender, RoutedEventArgs e)
    {
         if (this.openWindow != null)
         {
              // Show message box, active this.openWindow, close this
         }
         this.openWindow = this;
    }
}

如果您希望此窗口可重用,请确保设置this.openWindow = null;关闭窗口时也是如此。

答案 1 :(得分:3)

这是适合我的东西。

    private About aboutWin;
    private void AboutOpenClicked(object sender, RoutedEventArgs e)
    {
       if(aboutWin == null)
       {
           aboutWin = new About();
           aboutWin.Closed += (a, b) => aboutWin = null;
           aboutWin.Show();
       }
       else
       {

           aboutWin.Show();  
       }

    }

答案 2 :(得分:0)

最好将frmCaseWpf类设为singleton。这样你就不能创建另一个实例

答案 3 :(得分:0)

许多人使用会话(或系统)宽的“Mutex”或互斥锁,而不是尝试搜索Window实例。我打算为你重写一个,但我找到了一篇很好的代码项目文章,展示了这项技术。它并不复杂而且非常简单。

http://www.codeproject.com/KB/cs/SingleInstanceAppMutex.aspx?msg=2908697

先睹为快:

[STAThread]
static void Main()
{
    bool onlyInstance = false;
    Mutex mutex = new Mutex(true, "UniqueApplicationName", out onlyInstance);
    if (!onlyInstance) {
        return;
    }
    Application.Run(new MainForm);
    GC.KeepAlive(mutex);
}

希望这有帮助。

(编辑:当然,你必须根据你的特定用例略微修改它,但它会演示一般的想法)

答案 4 :(得分:0)

我不是一个'适当的'程序员,但我通过使用以下内容在WPF应用程序(而不是winforms)中实现了这一点:

Dim wdwDetails As New detailsNew()
Private Sub openNewDetails(ByVal recordID As String)
    wdwDetails.Owner = Me
    wdwDetails.recordID = recordID
    wdwDetails.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner
    wdwDetails.Show()
End Sub

基本上因为我在打开它的sub之外创建窗口对象,所以只有一个窗口。对窗口open sub的任何新调用都将使用相同的对象。但我想这也是托马斯所指的。

就像我说的那样,不确定这对你有没有帮助。

答案 5 :(得分:0)

您可以在创建新窗口之前使用XXXwindown.isLoad检查窗口是否已加载:

if ( !ChildWindow.IsLoaded)
{
   childWindow= new ChildWindow();
   childWindow.Show();
}