I have an application that has the start up window for the login, if the login is correct, it open the main window of the application.
When the login is correct, I open the new window in this way (I am using MVVM pattern):
PrincipalViewModel miPrincipalViewModel = new PrincipalViewModel();
PrincipalView miPrincipalView = new PrincipalView();
miPrincipalView.DataContext = miPrincipalViewModel;
App.Current.MainWindow.DataContext = null;
App.Current.MainWindow.Close();
miPrincipalView.Show();
In this case I don't set the new main window. Another option is this code:
PrincipalViewModel miPrincipalViewModel = new PrincipalViewModel();
PrincipalView miPrincipalView = new PrincipalView();
miPrincipalView.DataContext = miPrincipalViewModel;
App.Current.MainWindow.DataContext = null;
App.Current.MainWindow.Close();
App.Current.MainWindow = miPrincipalView;
miPrincipalView.Show();
In this second case, I set the main window property to the main window of the application, because the login window is closed.
But I don't see any difference in the behavior in both cases, so I am wondering what is really MainWindow and the use and meaning that is has.
Thank you.
In the first case you no longer have an actual MainWindow but that shouldn't be an issue unless you rely on the Application.Current.MainWindow property to return a valid reference to a window somewhere in your application or if you have set the Application.ShutdownMode property to OnMainWindowClose.
The default value is OnLastWindowClose which means that your application will shut down as expected when you close the new window anyway.
As the documentation on MSDN says "the lifetime of some applications may not be dependent on when the main window or last window is closed, or may not be dependent on windows at all.".
Here is part about what is App.Current.MainWindow from MSDN
MainWindow is automatically set with a reference to the first Window
object to be instantiated in the AppDomain. You can specify a
different main window by setting MainWindow assigning another Windows
object to the MainWindow property. If the ShutdownMode property of the
Application object is set to OnMainWindowClose, closing the main
window causes the application to shut down. It is possible to set the
MainWindow property from XAML, if an application's main window is not
the window that is produced by setting the StartupUri property in
XAML. The two limitations of the XAML approach are: You can specify
either a XAML-only Window or a XAML-only NavigationWindow as the main
window. You must set the Visibility property of the window you
specify, otherwise it won't be shown. The reference to the first
Window object to be instantiated is also added as the first item to
the Windows collection. If MainWindow is subsequently set with a
reference to a different Window, the position of the item with the
reference to the main window will change, while the order of items in
Windows remains the same. Consequently, always use MainWindow to refer
to the main window instead of the first item in Windows.
I think that you just need to set App.Current.ShutdownMode to ShutdownMode.OnExplicitShutdown before App.Current.MainWindow.Close(); and call App.Current.Shutdown when you will want to close the application.
MSDN Application.ShutdownMode
Related
suppose i have 2 windows: InputWindow and DisplayWindow
Currently:i want to use InputWindow to hold data via an App variable
// in InputWindow
(App.Current as App).u_id = obj.id;
where u_id is the object i defined in app.xaml.cs and obj.id is the input variable in InputWindow.
However when i close InputWindow and display DisplayWindow:
// in InputWindow
DisplayWindow window = new DisplayWindow();
window.Show();
Application.Current.MainWindow.Close();
The app also kill the data in the InputWindow.
So my question is:
Is there a way to keep the data via from the closed Window to the open Window?
Set Application.ShutdownMode to ShutdownMode.OnExplicitShutdown.
You can do this in you App.xaml, or anywhere else in C#.
<Application ... ShutdownMode="OnExplicitShutdown>
...
</Application>
Or in your App.xaml.cs:
ShutdownMode = ShutdownMode.OnExplicitShutdown;
Or somewhere else:
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
To shut down your application, you will need to call Application.Shutdown():
Application.Current.Shutdown();
You can also set Application.ShutdownMode to OnLastWindowClose, to shut down your application when the last window is closed (rather than when the main window is closed). You can do this in any of the ways described above.
However, it sounds like the only reason you want to keep your main window alive is so that you can use it as a data store. I recommend using a separate object as your data store, and referencing it both from your InputWindow and your DisplayWindow.
Application.Current.MainWindow.Hide();
You can hide the window using this line... or you can pass the information that you want to use into the new window using the constructor.
DisplayWindow window = new DisplayWindow(object myObject);
That constructor must have the information you want passed but this can solve the issue as well.
I am trying to use the SplashScreenService to show the user the progress of starting the application. Within the tasks I am creating the logger, the container, configuring the container, creating and initializing my MainWindow (View+ViewModel) and so on ... the tasks of a bootstrapper.
But the SplashScreenService refuses his work when committing because of Application.Current.MainWindow == null. The thing is that Application.Current.MainWindow is set within the initalization task.
I could workaround this with temporaly setting Application.Current.MainWindow = new Window() before the splashScreenService.Commit() and fixing the issue with MainWindow gets closed after SplashScreen is closed by setting the owner to null of my MainWindow (the owner was set to the PleaseWait dialog which therefor also closes the MainWindow).
So why must the Application.Current.MainWindow be set to get the SplashScreenService working? Within the service there is no code that uses this property. And I can only create my MainWindow after all other tasks are completed - a real chicken-and-egg problem!
I'm trying to get the window handle (HWND) of the main form of my C# application (the application has only 1 form).
Some solutions on the internet show that I can use:
Process.GetCurrentProcess().MainWindowHandle
to get the window handle of current process of my application. But this value is always zero, anything wrong?
MSDN says:
The main window is the window opened by the process that currently has the focus (the TopLevel form). You must use the Refresh method to refresh the Process object to get the current main window handle if it has changed.
and
A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden, that is, processes that are not visible in the taskbar. This can be the case for processes that appear as icons in the notification area, at the far right of the taskbar.
See http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle(v=vs.110).aspx
In properties [F4] window 'Show in Taskbar' should be True
try using
System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
I have the following C# code in a WPF project:
private static void RunConfig(string owner)
{
long ownerHandle;
var settingsWindow = new SettingsWindow();
if (long.TryParse(owner, out ownerHandle))
{
WindowInteropHelper helper = new WindowInteropHelper(settingsWindow);
helper.Owner = new IntPtr(ownerHandle);
}
settingsWindow.ShowDialog();
}
The SettingsWindow isn't properly modal to the owner window (i.e. I can focus on, interact with, and even close the owner window while the SettingsWindow is still open). What am I doing wrong?
For context, this code is part of a screen saver program, and the owner window is the Control Panel screen saver selection window (which passes in the handle to use as owner via command line parameter). I know the IF statement is evaluating true and correctly parsing the handle.
I have also tried using the SetWindowLongPtr method from user32.dll (compiling for x64, hence not using SetWindowLong) which is briefly described here and shown in use here. This method works in WinForms, but doesn't seem to work here in WPF. Help me Obi-Wan Kenobi, you're my only hope.
It turns out that using WindowInteropHelper to set the native window as owner of the WPF Window does work, it just doesn't do the whole job. When set this way, the WPF Window will remain visible on top of the native window, even if the native window has focus. However, that is the only effect obtained. The WPF Window does not prevent interaction with the native Window, and the native window can even be closed, without the WPF Window closing or being affected.
In order to get the rest of the desired behaviour, we need to use the EnableWindow function in user32.dll to disable the native Window before calling ShowDialog on the WPF Window, and again to re-enable it once the WPF Window closes.
The modified code looks like this:
private static void RunConfig(string owner)
{
long ownerHandle;
var settingsForm = new SettingsWindow();
if (long.TryParse(owner, out ownerHandle))
{
WindowInteropHelper helper = new WindowInteropHelper(settingsForm);
helper.Owner = new IntPtr(ownerHandle);
NativeMethods.EnableWindow(helper.Owner, false);
settingsForm.ShowDialog();
NativeMethods.EnableWindow(helper.Owner, true);
}
else
{
settingsForm.ShowDialog();
}
}
(Note: The above code is correct in general, but incomplete in the case of screen savers, which is what this code is actually being used for. In the case that this code is being used for the config window of a screen saver, the string passed in for the owner handle is not the handle of the Control Panel window to be used as owner, but rather a handle for a control that is a child of the Control Panel window. The extra step in this case is to get the handle of the parent of that control. We can do this by calling GetParent, also in user32.dll, on the passed-in handle. This will return the real handle we want to use for the owner and EnableWindow calls.)
If anyone from Microsoft ever finds this, maybe consider modifying WindowInteropHelper to properly set all of this up when Owner is assigned and ShowDialog used, since this is the proper complete behavior for modal windows.
I'm trying to create a custom MessageBox by using a WPF Window that is called with ShowDialog().
So far, I've managed to implement everything, except for one thing.
As you know, when you use MessageBox.Show("text"); you cannot set the focus or click the parent window (the one that called the MessageBox). If you do try to click the parent window, the MessageBox will blink briefly in order to alert you that you must close if first.
Windows created with Window.ShowDialog();, however, do not show that behavior. In fact, while you cannot set the focus to the parent window, the child (called with ShowDialog()) will never blink briefly.
My question is, is there any way to implement that in WPF? I've been searching for an answer but I must admit, I am stumped.
Thanks everyone!
You need to set the Owner of the modal window correctly, e.g. using the following code from within the owning window:
Window win = new SomeModalWindow();
win.Owner = this;
win.ShowDialog();
You would have to set Owner property of the child Window to the parent Window. See the MSDN Documentation here.