问题
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