How can I make sure only one WPF Window is open at a time?

百般思念 提交于 2019-12-30 10:26:21

问题


I have a WPF window that I am launching from inside of a winform app. I only want to allow once instance of that WPF window to be open at a time, and not warn that user if they try to open it again.

I am having a problem however trying to search for that WPF window being open because the window is being launched from a winform. What I normaly do is when searching for a winform, I search for any instances of that winform existing in the Application.Current.OpenForms, and when in WPF I search for Application.Current.Windows

The problem I have is that System.Windows.Application.Current is null when launched from inside of a winform, so I can't search for the WPF window that way. Is there any better way of searching for an existing instance of an open window?

My Code:

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

回答1:


Instead of searching the static application objects, you could instead just track this within your window, with a single static variable. Just keep a variable in the window:

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

When you create a window, either in the initialize routines, or OnLoaded, depending on how you want it to work..:

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

If you want this window to be reusable, make sure to set this.openWindow = null; when you close the window, as well.




回答2:


Here's something that's working for me.

    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:


It would be better make the frmCaseWpf class a singleton. That way you can't create another instance




回答4:


Rather than try to search for a Window instance, many people use a session- (or system-) wide "Mutex" or a Mutual Exclusion lock. I was going to rewrite one for you, but I found a good codeproject article demonstrating the technique. It's not complex and very simple.

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

Sneak peek:

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

Hope this helps.

(edit: of course you'll have to modify this slightly for your particular use-case, but it demos the general idea)




回答5:


I am not really a 'proper' programmer, however I have achieved this in a WPF application (not from a winforms one) by using the following:

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

Essentially because I am creating the window object outside of the sub that opens it, there will only be a single window. Any new call to the window open sub will use the same object. But I guess that is what Thomas is referring to also.

Like I said, not sure if this will help you or not though.




回答6:


You can use XXXwindown.isLoad to check if window is loaded before you create a new window:

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


来源:https://stackoverflow.com/questions/1335785/how-can-i-make-sure-only-one-wpf-window-is-open-at-a-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!