Closing of a WPF Window still visible in taskbar - c#

I have a small issue with my WPF application.
I have a splash image (as a XAML Window) and the main app (as another XAML window that gets caleld from Splash)
Even when I use this .Close() on Splash window and work on Main app, the Splash window is still visible in taskbar.
If I were to use this .Close on main app I would have two blank windows in taskbar application that I have to press X to close completely.
I've tried with Application.Current.Shutdown() as well but results were same.
Splash:
public Splash()
{
InitializeComponent();
}
private void Window_ContentRendered(object sender, EventArgs e)
{
CloseProcedure();
}
public async void CloseProcedure()
{
//Missing data loading which will be async.
UC_Main UCMain = new UC_Main();
MainWindow window = new MainWindow();
window.AppContent.Children.Add(UCMain);
this.Close();
await Task.Delay(500); //for fade effect.
window.Show();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Closing -= Window_Closing;
e.Cancel = true;
var anim = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(0.5));
this.BeginAnimation(UIElement.OpacityProperty, anim);
anim.Completed += (s, _) => this.Close();
}
Main App
private void BTN_Close_MouseUp(object sender, MouseButtonEventArgs e)
{
this.Close();
}
private void titleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
titleBar.Background = Brushes.White;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Closing -= Window_Closing;
e.Cancel = true;
var anim = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(0.2));
this.BeginAnimation(UIElement.OpacityProperty, anim);
anim.Completed += (s, _) => Application.Current.Shutdown();
}
}

The default shutdown mode of a WPF app is "OnLastWindowClose" which means as soon as the last window is closed, the applicaton shutdown procedure will be called, so you should not need to explicitly write System.Windows.Application.Shutdown().
You probably have something referencing the splash screen that isn't being closed off. When you open your main window, you should close the splash screen properly at that time and ensure that any reference to it is null.
If you post all your code, it will be easier to know the correct fix.
To prevent a window showing in the taskbar in the first place, set the ShowInTaskbar property of your Window XAML declaration:
<Window ShowInTaskbar="False" ...

I've come up with a solution for this.
Instead of trying to shut down the process and animate the fade inside the closing event handler, I wrote an asynchronous method that will fade out the screen, await for the same amount of time and then kill the process. Works like a charm.
private void BTN_Close_MouseUp(object sender, MouseButtonEventArgs e)
{
this.FadeOut();
}
async private void FadeOut()
{
var anim = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(0.2));
this.BeginAnimation(UIElement.OpacityProperty, anim);
await Task.Delay(200);
this.Close();
System.Diagnostics.Process.GetCurrentProcess().Kill();
}

Related

Where do I put custom code to handle a resize event C# windows form

I cannot work out where to put nor get the code to trigger when my main form windows are resized (ie minimize button clicked)
I am trying to trigger this code when ANY resize of the DigiDocketMain window is minimized etc, or also how I can specifically code the minimize button to do something - the ideal goal is to get the program - n minimize button click to hide the taskbar icon and show a tray icon.
I have tried placing this is the main code body and the designer code but nothing triggers it. any help would be appreciated.
private void DigiDocketMain_Resize(object sender, System.EventArgs e)
{
MessageBox.Show("You are in the Form.ResizeEnd event.");
if (this.WindowState == System.Windows.Forms.FormWindowState.Minimized)
{
this.Hide();
mainTrayIcon.Visible = true;
}
}
In your code behind add the following to the Form_Load Event
this.SizeChanged += Form1_SizeChanged;
Then implement the function, autocomplete may do this for you.
private void Form1_SizeChanged(object sender, EventArgs e)
{
// Add the code that will be called on resize events.
}
According to your description, when clicking the minimize button, you want to hide the
taskbar icon and display the tray icon.
I suggest that you set the Visible of notifyIcon1 to false in the property bar, and select a icon format image as the icon, then try the following code.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Deactivate(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.notifyIcon1.Visible = true;
this.Hide();
this.ShowInTaskbar = false;
}
}
private void notifyIcon1_Click(object sender, EventArgs e)
{
this.Visible = true;
this.WindowState = FormWindowState.Normal;
this.notifyIcon1.Visible = false;
this.ShowInTaskbar = true;
}
}

How to do not freeze wpf app on closing event

I have a WPF app and I want to execute some method in the Closing event. It can take several minutes, that's why the WPF window freezes. Here is my code:
public MainWindow()
{
InitializeComponent();
this.Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Task.Run(new Action(ClaseAfterThreeSecond)).Wait();
}
void ClaseAfterThreeSecond()
{
Thread.Sleep(3000);
}
I want to do not freeze the WPF app until MainWindow_Closing ends when I click the X button (close button) on the WPF app. Any suggestions?
EDIT:
This way closes the window immediately. I don't need this:
async void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
await Task.Run(new Action(ClaseAfterThreeSecond));
}
You need to make your handler async, but as it async void it returns right after your first await call. Just cancel original closing event and close directly in your code:
private async void Window_Closing(object sender, CancelEventArgs e)
{
// cancel original closing event
e.Cancel = true;
await CloseAfterThreeSeconds();
}
private async Task CloseAfterThreeSeconds()
{
// long-running stuff...
await Task.Delay(3000);
// shutdown application directly
Application.Current.Shutdown();
}

WPF C# Windows throws "Application has stopped working" upon Application.Current.Shutdown(); call

I'm in process of learning C# and WPF specifically. I have a program currently written but it's having an issue closing. When a user closes the main window, the program ends, but the process continues running in the background. Each time a new window is open, a new process is created and never ends. I attempted to fix this by adding the following code to my MainWindow.xaml.cs file:
private void InventoryUpdater_Closed(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
This closes the process but causes a window to pop up that acts like the program shutdown incorrectly and prompting the user to "Close the program". That window states, "[Application Name] has stopped working.
How can I end my application process without it prompting the user each time they want to close? Is it possible I've not properly disposed something?
So I figured out what was causing the prompt and what was causing the unending process.
The prompt had to do with my opening and closing of the other 3 windows. Here is what I changed to stop getting the error from Application.Current.Shutdown(). I changed this code:
private void settingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
updateSettings();
e.Cancel = true;
main.Show();
Hide();
}
private void settingsButton_MouseUp(object sender, RoutedEventArgs e)
{
settingsWindow settingsWindow = new settingsWindow(this);
if (!settingsWindow.settingsOpen)
{
settingsWindow.Show();
Hide();
}
}
To this code:
private void settingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
updateSettings();
}
private void settingsButton_MouseUp(object sender, RoutedEventArgs e)
{
settingsWindow settingsWindow = new settingsWindow(this);
if (!settingsWindow.settingsOpen)
{
settingsWindow.ShowDialog();
}
}
Once I close main it was going back through the other window instances that I had initialized on load and was cycling through their Closing events. Once it was getting to main.Show(), it was failing to Show something that had already been closed.
Once I did that, I was about to figure out that the original initializing of the additional windows in my Loaded event was causing the additional trace backs that weren't ending. Here is what I changed. I changed this:
private void InventoryUpdater_Loaded(object sender, RoutedEventArgs e)
{
settingsWindow settings = new settingsWindow(this);
sftpSettings severSettings = new sftpSettings(settings);
TimeSpan na = queueCustomTask();
Stop = true;
runManually.IsEnabled = true;
ssdRunManually.IsEnabled = true;
startAutoRun.IsEnabled = true;
}
To this:
private void InventoryUpdater_Loaded(object sender, RoutedEventArgs e)
{
TimeSpan na = queueCustomTask();
Stop = true;
runManually.IsEnabled = true;
ssdRunManually.IsEnabled = true;
startAutoRun.IsEnabled = true;
}
I'm not even sure why the initializing was still there. Everything had been switched to static global variables so removing those two lines affected nothing. Thanks for all the shoves in the right direction!

I want to run a function when ever the form is clicked on taskbar and it opens

The issue doing so is i have used tips and tricks here but the seems to run in a loop and wont give the results.
Basically i run a BackgroundWorker to hit a url get result and paste result to some Labels.
I have used Form_Activated but it just keeps on running in a loop and wont stop ever reached to the BackgroundWorker completed event .
MAIN CODE BLOCKS:
On Form_Load I Run the Function and get the results and show:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Show();
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
else
{
MessageBox.Show("Thread already running....");
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
loadData(); // scrape a URL and paste info to Labels ....
}
This is it, now the user will minimize the application , now whenever he hits the the taskbar icon the form should rerun the same as in Form_Load. I hope that make sense , i have been able to do that using Form_Activate but it keeps going on .
Any suggestion how to get it done ?
I would store a boolean to remember if the form was minimized at the last FormResized event, and then if it was and if the form isn't currently minimized then call your method.
private bool minimized = false;
public void FormResized(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
minimized = true;
}
if (minimized && this.WindowState != FormWindowState.Minimized)
{
minimized = false;
MyMethod();
}
}

Observe which window sent a Close() event

I have a short questions and even after a while of searching through the web I have not found the answer.
I have two windows in a WPF application. One window should just be hidden when the user closes it. When the main window is closed the complete application shall close.
I used
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
Hide();
}
inside the class of the second window and hoped it would just catch its Close() event but unfortunately it catches all Close() events.
How can I separate between the windows to handle the events independently?
Regards
Larimow
Use the sender parameter, that's what it's there for:
window1.Closing += Window_Closing;
window2.Closing += Window_Closing;
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
var w = (Window)sender;
// Simple ref test to illustrate, but you can use anything else you want instead
if (w == window1) {
e.Cancel = true;
w.Hide();
}
}

Categories