Quitting WPF Application after Window Closed - c#

I have a method in class where I call loginWindow.ShowDialog(); which brings up a Window, however when you press Close (X in top right) it doesn't Quit the application, rather continues to run whatever is below loginWindow.ShowDialog(); in that method.
How am I able to quit the application entirely if that Window is closed?
I tried to use:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
System.Windows.Application.Current.Shutdown();
base.OnClosing(e);
}
Although this didn't shut the application down, which confuses me. When I was using loginWindow.Show(); this wasn't a problem.

I don't know how your application runs, based on your sample code I have two solutions.
Solution 1:- Every window has DialogResult property. Inside the OnClosing event assign DialogResult = true; and call the Shutdown method. The windows who is responsible to call will get the result from return value of ShowDialog() method
For example:-
private void SecondWindow_OnClosing(object sender, CancelEventArgs e)
{
DialogResult = true;
System.Windows.Application.Current.Shutdown();
}
Below event, is from the First screen, calling the Second Window.
private void Button_Click(object sender, RoutedEventArgs e)
{
SecondWindow secondWindow = new SecondWindow();
var dialogResult = secondWindow.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value == false)
{
// any code of yours which must not be executed after the second
// window has closed the process
}
}
Once, the DialogResult is assigned true, the first window will check only if it is false execute the below code or else ignore.
Solution 2:- We will get the Current Application Running Process and Kill the whole process that is your whole application.
private void SecondWindow_OnClosing(object sender, CancelEventArgs e)
{
Process.GetCurrentProcess().Kill();
}

There is a shutdown mode that you can define in the App.Xaml
The default option is OnLastWindowClosed. If it is OnExplicitShutdown than the application wants you to call Application.Shutdown(). What this means is, if you close all windows the application is still running because it is expecting a Application.Shutdown() to be called. This is an explicit shutdown.
Other two options are implicit meaning the Application.Shutdown() method will be called when the last window is closed or when the main window is closed.
Can you check what option you have defined?

Related

How do I show a new window after having closed the MainWindow?

I'm trying to do what is described in this post, display a log in window and when user successfully logs in, close it and open the main window of the application.
If the user logs on successfully, then I want to show the main window, if not, I want to exit the application
but the provided answers (at the time of posting this question) do not work for me since my code to show the windows is running from the App.cs.
I know the reason, its because the first window that starts up is automatically set to be the MainWindow of the application and when I call Close() on it, it exits the application. So the second window doesn't have a chance to open.
My question is how to overcome this? Or is this just not possible the way I described?
public partial class App : Application
{
public App(){}
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginScreen f = new LoginScreen(); //becomes automatically set to application MainWindow
var result = f.ShowDialog(); //View contains a call to Close()
if (result == true) //at this point the LoginScreen is closed
{
MainWindow main = new MainWindow();
App.Current.MainWindow = main;
main.Show(); //no chance to show this, application exits
}
}
}
You can change application shutdown mode to OnExplicitShutdown and then call Application.Shutdown(0) whenever you want to. For example:
public App()
{
App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (MessageBox.Show("Continue?", "", MessageBoxButton.YesNo) == MessageBoxResult.No)
App.Current.Shutdown(0);
}
Here in the constructor I'm changing application shudown mode and calling Shutdown method if I need to.
Caution: When you change ShutdownMode make sure to call Shutdown method otherwise your application will be in memory even after main window closes. I've overrided OnClosed method in my MainWindow to do that:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown(0);
}
App.xaml : (In this file set the start window with the login view)
StartupUri="LoginWindow.xaml"
LoginWindow.xaml : (A file with a login window view)
LoginWindow.xaml.cs : (Code Behind for the view. Place here the function assigned to login. )
private void Login_Click(object sender, RoutedEventArgs e)
{
//Access control. If correct, go ahead. Here you must create a condition check
MainWindow main = new MainWindow();
main.Show();
this.Close();
}

WPF close all window from the main window

I have login window. From this login window, i am intializing the main window.
Once login successfully happened, i close the login window.
Now i am having two other windows, which i am calling from Main Window.
Once i close the main Window, I am able to close the other two windows as well as Main Window.
But program still runs in memory. I have to close it manually from the Visual Studio.
How should i close the Program all instances fully??
This is the Main window Close Event code.
private void usimClose(object sender, EventArgs e)
{
newScreen2.Close();
newScreen3.Close();
this.Close();
}
This is my Login Window Code. Once the user click on the submit button.
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
if (txtUserName.Text.Length == 0)
{
errormessage.Text = "Please Enter UserName";
txtUserName.Focus();
}
else
{
LoginStatus _status = _Login.LoginUsimgClient(txtUserName.Text, txtPassword.Password.ToString());
if (_status.BoolLoginstatus)
{
mainWindow.RunApplication();
string struserName = _status.StringUserFirstName;
mainWindow.userName.Text = "Welcome " + struserName;
mainWindow.Show();
this.Close();
}
else
{
errormessage.Text = _status.StringErrorDescription;
txtUserName.Text = String.Empty;
txtPassword.Password = String.Empty;
}
}
}
Try Application.Current.Shutdown();
From MSDN
Calling Shutdown explicitly causes an application to shut down,
regardless of the ShutdownMode setting. However, if ShutdownMode is
set to OnExplicitShutdown, you must call Shutdown to shut down an
application.
Important note
When Shutdown is called, the application will shut down irrespective
of whether the Closing event of any open windows is canceled.
This method can be called only from the thread that created the
Application object.
You can close all windows using this
App.Current.Shutdown();
or
you can manually close it
Window parentwin = Window.GetWindow();
parentwin.Close();
If you starting point is your MainWindow, then just start there.
Firstly, host the LoginForm in your MainWindow, and show it using ShowDialog() to force the user to interact with the LoginForm. Return the result of a successful/unsuccessful interaction to the MainForm.
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
var form = new LoginForm();
var result = form.ShowDialog();
if (result ?? false)
{
// Carry on opening up other windows
}
else
{
// Show some kind of error message to the user and shut down
}
}
Otherwise, technically your LoginForm is hosting your MainForm which is, frankly, odd.
Have a look at my answer here: How to close wpf window from another project
An Application.Current.Shutdown() will stop the application in a very abrupt way.
It is better to gracefully keep track of the windows and close them.

why this.close() close application

I have a window in wpf that i want on the escape button to close the window. So i wrotethis code on PreviewKeyDown event, but it closes the entire application, including the main window and current window. I just want to close current window.
//this code for open second window
private void M_Mahale_Click(object sender, RoutedEventArgs e)
{
Tanzimat.MahaleWin Mahale = new Tanzimat.MahaleWin();
Mahale.ShowDialog();
}
//this code for PreviewKeyDown event on second window and current window
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
this.Close();
}
}
OK, based on this comment //this code for PreviewKeyDown event on second window and current window you have the same code in both windows in the PreviewKeyDown -so in both windows change the code to this:
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
e.Handled = true;
this.Close();
}
}
and that will keep other windows from getting the event when it's been handled already. See, what's happening is when the escape key is pressed both windows are getting the message, and you didn't tell the main window (i.e. the one behind the current one) not to process it.
You window has a name Mahale and or order to close it from the main window, you should call:
Mahale.Close();
If you call this.Close(); in main form it is quite natural for the program to exit
You can use this.Hide() to hide that window, but that window still exists.
I think the best way to achieve your goal is using of Button's IsCancel property.
You can set the IsCancel property on the Cancel button to true,
causing the Cancel button to automatically close the dialog without
handling the Click event.
See here for examples.
do :
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
this.Hide();
}
}
instead.
Close() close every frames. Use hide().

NotifyIcon remains in Tray even after application closing but disappears on Mouse Hover

There are many questions on SO asking same doubt.
Solution for this is to set
notifyIcon.icon = null and calling Dispose for it in FormClosing event.
In my application, there is no such form but has Notification icon which updates on Events.
On creation, I hide my form and make ShowInTaskbar property false. Hence I can not have a "FormClosing" or "FormClosed" events.
If this application gets event to exit, It calls Process.GetCurrentProcess().Kill(); to exit.
I have added notifyIcon.icon = null as well as Dispose before killing, but still icon remains taskbar until I hover mouse over it.
EDIT: If I assume that this behaviour is due to calling GetCurrentProcess().Kill(), Is there any elegant way to exit from application which will clear all resources and remove icon from system tray.
You can either set
notifyIcon1.Visible = false;
OR
notifyIcon.Icon = null;
in the form closing event.
The only solution that worked for me was to use the Closed event and hide and dispose of the icon.
icon.BalloonTipClosed += (sender, e) => {
var thisIcon = (NotifyIcon)sender;
thisIcon.Visible = false;
thisIcon.Dispose();
};
Components just must be disposed in the right order like this :
NotifyIcon.Icon.Dispose();
NotifyIcon.Dispose();
Add this to the MainWindow closing event.
Hope this will help.
Use this code when you want to do it when you press the Exit or Close button:
private void ExitButton_Click(object sender, EventArgs e)
{
notifyIcon.Dispose();
Application.Exit(); // or this.Close();
}
Use this code when you want to do it when the form is closing:
private void Form1_FormClosing(object sender, EventArgs e)
{
notifyIcon.Dispose();
Application.Exit(); // or this.Close();
}
The important code is this:
notifyIcon.Dispose();
Use notifyIcon.Visible = False in FormClosing event
This is normal behaviour, unfortunately; it's due to the way Windows works. You can'r really do anything about it.
See Issue with NotifyIcon not dissappearing on Winforms App for some suggestions, but none of them ever worked for me.
Also see Notify Icon stays in System Tray on Application Close
Microsoft have marked this as "won't fix" on Microsoft Connect.
The only way that works to me was:
On design screen changing notifyicon1 property visible=false
Insert the code below on main form "activated" event:
NotifyIcon1.Visible = True
Insert the code below on main form "closing" event:
NotifyIcon1.Visible = false
NotifyIcon1.Icon.Dispose()
NotifyIcon1.Dispose()
I don't think WPF has it's own NotifyIcon, does it? If you're using the 3rd party Harcodet.Wpf.TaskbarNotification, then try this:
In order to prevent my app from closing when the window is closed (run in background), I separated the logic for closing the window (hitting the x button in the upper right) and actually shutting it down (through the context menu). To make this work, make your context menu set _isExplicitClose to true. Otherwise, it'll just hide the window and continue to run.
What this does is, on explicit close, hide tray icon and the form before closing. This way the icon isn't hanging around after the application is shutdown.
private bool _isExplicitClose;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (!_isExplicitClose)
{
e.Cancel = true;
Hide();
}
}
protected void QuitService(object sender, RoutedEventArgs e)
{
_isExplicitClose = true;
TaskbarIcon.Visibility = Visibility.Hidden;
Close();
}
Try Application.DoEvents(); after setting notifyIcon.Icon to null and disposing:
notifyIcon.Icon = null;
notifyIcon.Dispose();
Application.DoEvents();
And consider Environment.Exit(0); instead of Process.GetCurrentProcess().Kill().
i can tell you can solve the problem simply using the .dispose() method, but that is not called if you kill the process instead of exit the application.
please refer to Application.Exit if you have built a simple Windows Form application else refer to Environment.Exit that is more general.
I tried all of these and none of them worked for me. After thinking about it for a while I realized that the application creating the "balloon" was exiting before it had a chance to actually dispose of the balloon. I added a while loop just before Application.Exit() containing an Application.DoEvents() command. This allowed my NotifyIcon1_BalloonTipClosed to actually finish disposing of the icon before exiting.
while (notifyIcon1.Visible)
{
Application.DoEvents();
}
Application.Exit();
And the tip closed method: (You need to include the thisIcon.visible = false in order for this to work)
private void NotifyIcon1_BalloonTipClosed(object sender, EventArgs e)
{
var thisIcon = (NotifyIcon)sender;
thisIcon.Icon = null;
thisIcon.Visible = false;
thisIcon.Dispose();
}
I had the exact same problem as you.
The proper way are send WM_CLOSE message to a process.
I use the c# code I found in this article.
http://social.msdn.microsoft.com/Forums/vstudio/en-US/82992842-80eb-43c8-a9e6-0a6a1d19b00f/terminating-a-process-in-a-friendly-way
edit codes of ...Designer.cs as below coding.
protected override void Dispose(bool disposing)
{
if (disposing )
{
this.notifyicon.Dispose();
}
base.Dispose(disposing);
}
I couldn't make any one of the other solutions work. It turned out to be kind of a hybrid of all the above! I hunted and pecked until I had a consistently working solution both in debug and in EXE execution modes! I have no idea why MSFT would mark this as "Not going to fix"? I wish I had that liberty!
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
//THIS CODE IS CRAZY BUT MUST BE DONE IN ORDER TO PROPERLY REMOVE THE SYSTEM TRAY ICON!
//GREAT ARTICLE ON THIS ON STACK OVERFLOW
//https://stackoverflow.com/questions/14723843/notifyicon-remains-in-tray-even-after-application-closing-but-disappears-on-mous
//BTW THIS IS KIND OF A BLEND OF ALL THE SOLUTIONS BECAUSE I COULD NOT FIND A SINGLE SOLUTION THAT WOULD WORK!
systray_icon.Visible = false;
while (systray_icon.Visible)
{
Application.DoEvents();
}
systray_icon.Icon.Dispose();
systray_icon.Dispose();
Environment.Exit(1);
}
The right answer has already been given. But you must also provide a delay, for example with a timer. Only then the application can still remove the icon in the background.
private System.Windows.Forms.Timer mCloseAppTimer;
private void ExitButton_Click(object sender, EventArgs e)
{
notifyIcon.Visible = false; notifyIcon.Dispose;
mCloseAppTimer = new System.Windows.Forms.Timer();
mCloseAppTimer.Interval = 100;
mCloseAppTimer.Tick += new EventHandler(OnCloseAppTimerTick);
}
private void OnCloseAppTimerTick(object sender, EventArgs e)
{
Environment.Exit(0); // other exit codes are also possible
}

Lock menu item when window open, unlock when closing

I have a window that I want to allow only one instance of it to be open at a time. They can open / close the window, but can't have multiple copies of the same window open at a time.
I have a menu with an option that when clicked, opens the ProductSelection window. ListProductList is my button:
private void ListProductListCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = _productListCanExecute;
//_productListCanExecute = !_productListCanExecute;
}
private void ListProductList(object sender, ExecutedRoutedEventArgs e)
{
_productListCanExecute = false;
ProductSelection pl = new ProductSelection(productCategoryList, productStyleList, productList);
pl.Show();
}
Notice that I set the e.CanExecute of the ListProductList button to false to ensure that the event handler doesn't run and therefore doesn't open more windows.
Now, how can I detect that the ProductSelection window has closed in order to set the _productListCanExecute back to true? It's not a modal window, because I want to allow them to do other things.
Probably the easiest solution here is to make the pl variable a global.
Whenever the button is clicked, just "show" that existing window.

Categories