【问题标题】:How can I make sure only one WPF Window is open at a time?如何确保一次只打开一个 WPF 窗口?
【发布时间】:2010-11-23 01:48:31
【问题描述】:

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

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

我遇到的问题是System.Windows.Application.Current 在从 winform 内部启动时为空,因此我无法以这种方式搜索 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;
                        }
                    }
                }

【问题讨论】:

    标签: c# wpf winforms .net-3.5


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      这对我有用。

          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();  
             }
      
          }
      

      【讨论】:

        【解决方案3】:

        我并不是真正的“合格”程序员,但是我通过使用以下方法在 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 之外创建窗口对象,所以只会有一个窗口。对窗口打开子的任何新调用都将使用相同的对象。但我想这也是 Thomas 所指的。

        就像我说的,但不确定这是否会对您有所帮助。

        【讨论】:

        • 显然我的也是 VB 而不是 C#。 :)
        【解决方案4】:

        许多人没有尝试搜索 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);
        }
        

        希望这会有所帮助。

        (编辑:当然,您必须针对您的特定用例稍作修改,但它演示了总体思路)

        【讨论】:

        • 这不是 Russ 所要求的......他不是要制作单实例应用程序,他只是希望应用程序的特定窗口只显示一次
        • 呃,对。我误读了。那有多难?用静态标志跟踪它……哎呀。
        • @x0n- 这就是我选择答案的原因,因为使用静态标志跟踪它解决了我的问题。这很难,因为我从来没有这样做过,而且我团队中的其他人都被解雇了很久,所以没有太多其他人可以解决问题了。我在网上也没有看到很多关于 winforms 和 wpf 之间互操作的信息,我对这个特定的应用程序非常感兴趣。
        【解决方案5】:

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

        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;当你关闭窗口时,也是​​如此。

        【讨论】:

        • 我使用的是 .NET 4.5 并且 this.OpenWindow 不存在。有其他选择吗?
        • @valsidalv 我认为他的意思是让frmCaseWpf 类成为单身人士。 openWindow其实是他在frmCaseWpf中声明的一个变量
        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-06-30
          • 1970-01-01
          • 1970-01-01
          • 2020-02-18
          • 1970-01-01
          • 2021-07-21
          • 1970-01-01
          相关资源
          最近更新 更多