I'm looking for the best way to intercept the closing of a window in my software. For example I want to intercept the closure of a form called "settings", and not the MainWindow. vb.net of the procedure was very simple, I had only to call its closing event, but with WPF I can not understand why this event is not captured, and as a result, the code inside is not executed.
In the form you want to intercept the closing for:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if(dontClose)
{
e.Cancel = true;
}
base.OnClosing(e);
}
Replace dontClose with your conditions for not closing.
In the cs file behind your XAML, add this:
// Constructor
public SettingsWindow()
{
InitializeComponent();
Closing += SettingsWindow_Closing; // Subscribe to window closing event.
}
// Window closing event handler.
private void SettingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Add method you want to run on close here.
}
You can acces it from the view model as well if you have one. Like this
Application.Current.MainWindow.Closing += (s, e) =>{ your code comes here};
Related
How can I get my windows form to do something when it is closed.
Handle the FormClosed event.
To do that, go to the Events tab in the Properties window and double-click the FormClosed event to add a handler for it.
You can then put your code in the generated MyForm_FormClosed handler.
You can also so this by overriding the OnFormClosed method; to do that, type override onformcl in the code window and OnFormClosed from IntelliSense.
If you want to be able to prevent the form from closing, handle the FormClosing event instead, and set e.Cancel to true.
Or another alternative is to override the OnFormClosed() or OnFormClosing() methods from System.Windows.Forms.Form.
Whether you should use this method depends on the context of the problem, and is more usable when the form will be sub classed several times and they all need to perform the same code.
Events are more useful for one or two instances if you're doing the same thing.
public class FormClass : Form
{
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
// Code
}
}
WinForms has two events that you may want to look at.
The first, the FormClosing event, happens before the form is actually closed. In this event, you can still access any controls and variables in the form's class. You can also cancel the form close by setting e.Cancel = true; (where e is a System.Windows.Forms.FormClosingEventArgs sent as the second argument to FormClosing).
The second, the FormClosed event, happens after the form is closed. At this point, you can't access any controls that the form had, although you can still do cleanup on variables (such as Closing managed resources).
Add an Event Handler to the FormClosed event for your Form.
public class Form1
{
public Form1()
{
this.FormClosed += MyClosedHandler;
}
protected void MyClosedHandler(object sender, EventArgs e)
{
// Handle the Event here.
}
}
public FormName()
{
InitializeComponent();
this.FormClosed += FormName_FormClosed;
}
private void FormName_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
{
//close logic here
}
Syntax :
form_name.ActiveForm.Close();
Example:
{
Form1.ActiveForm.close();
}
I have 2 fullscreen window in my Gtk# application, primary and secondary. I have buttonClose in second form's that click event handler must close this window and make some operation:
protected void OnButtonClose_Clicked (object sender, EventArgs e)
{
//some operation
this.Dispose ();
}
But window doesn't close! If I use this code in Primary window, that window will close and application will terminate. Why this code works for primary window and doesn't works for secondary? How can I close secondary window?
Try Window.Destroy() should destroy the window for the secondary window. You could also hide it with .Hide() but not sure that's your intention
After a ton of research on this I have found what seems to work correctly for me.
public WhateverWindow():base (Gtk.WindowType.TopLevel) {
DeleteEvent += delegate { Application.Quit(); };
}
try using the DeleteEvent += delegate { Application.Quit(); };
in your function see if that doesn't help.
use this:
protected void OnBtnCancelarClicked (object sender, EventArgs e)
{
this.Destroy ();
}
It seems that the only method that works as expected is calling:
RootWindow.Destroy ();
However, ain't sure if that's the right way to do it.
I have a WinForm that I create that shows a prompt with a button. This is a custom WinForm view, as a message box dialog was not sufficient.
I have a background worker started and running. I also want to exit the while(aBackgroundWorker.IsBusy) loop if the button on myForm was clicked.
//MyProgram.cs
using(CustomForm myForm = new CustomForm())
{
myForm.Show(theFormOwner);
myForm.Refresh();
while(aBackgroundWorker.IsBusy)
{
Thread.Sleep(1);
Application.DoEvents();
}
}
Right now, in the CustomForm the Button_clicked event, I have
//CustomForm.cs
private void theButton_Click(object sender, EventArgs e)
{
this.Close();
}
Do I need to add more code to the CustomForm class, or the location where I declare and initialize the form in order to be able to detect a closure?
To detect when the form is actually closed, you need to hook the FormClosed event:
this.FormClosed += new FormClosedEventHandler(Form1_FormClosed);
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Do something
}
Alternatively:
using(CustomForm myForm = new CustomForm())
{
myForm.FormClosed += new FormClosedEventHandler(MyForm_FormClosed);
...
}
void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
// Do something
}
You might be going overkill. To show a form like a dialog window and wait for it to exit before returning control back to the calling form, just use:
mySubForm.ShowDialog();
This will "block" the main form until the child is closed.
Make sure your background worker supports cancellation and as others have pointed out use the form closed event handler. This code should point you in the right direction:
using(CustomForm myForm = new CustomForm())
{
myForm.FormClosed += new FormClosedEventHandler(ChildFormClosed);
myForm.Show(theFormOwner);
myForm.Refresh();
while(aBackgroundWorker.IsBusy)
{
Thread.Sleep(1);
Application.DoEvents();
}
}
void ChildFormClosed(object sender, FormClosedEventArgs e)
{
aBackgroundWorker.CancelAsync();
}
Handle the FormClosing event of the form to be notified when the form is closing, so you can perform any cleanup.
You should be able to hook into the FormClosing and FormClosed events.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosing.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosed.aspx
Closing is before it's closed.
Closed is after it's closed.
A couple things...
First, it appears that loop is there in order to prevent execution form proceeding while the dialog is open. If that is the case, change you .Show(parent) to .ShowDialog(parent). That will also take care of the rest of your question.
Note that this.Hide(); is not the same as this.Close(); in the actual dialog your overriding the closed event
Is it possible? I need to call the Form1_FormClosing here:
ContextMenu trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Close", delegate {
Form1_FormClosing(????)
});
I need it because I'm using the CancelEventArgs from _FormClosing event:
private void Form1_FormClosing(object sender, CancelEventArgs e)
{
if (th != null && th.ThreadState == System.Threading.ThreadState.Running)
{
if (MessageBox.Show("the process is running, you want stop it?", "app", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
AbortProccess(); }
else
{
e.Cancel = true;
}
}
}
I hope this is clear,thanks in advance.
There are a few things you could do.
First, you could just close the form using myForm.Close() as this will indirectly call the FormClosing event. Also, you could move everything within the FormClosing event into a separate method instead of in the event itself. You can then call that method from the event and from your MenuItem. If you don't want to do either of those, you could try using this as the delegate:
//CancelEventArgs can also take a boolean which dictates if
//it should be cancelled
Form1_FormClosing(this, new CancelEventArgs());
This is technically possible, just call the OnFormClosing() method. But that doesn't actually close the form, it should only ever run when the form actually closes. Pretending that the form is closing when it is not actually closing is going to lead to disappointment.
So just call the Close() method instead.
ContextMenu trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Close", delegate {
this.Close();
});
I found this:
Button with an X at the upper-right corner of the form, how to catch this event # C#
Which says I should use the FormClosing event to find out when the window is closing because of a click on the X.
But my event code never gets called:
private void MainWin_FormClosing(Object sender, FormClosingEventArgs e)
{
m_closeThread = true;
Application.Exit();
}
I must be missing something basic, but I don't know what.
You must either subscribe to the event like:
this.FormClosing += this.MainWin_FormClosing;
in the form's constructor (or somewhere), or use:
override void OnFormClosing(FormClosingEventArgs e)
{
m_closeThread = true;
Application.Exit();
}
Make sure that you're correctly subscribing to the FormClosing event.
You must have on your MainWin dialog (tipically in the constructor), something like this:
this.FormClosing += new FormClosingEventHandler(MainWin_FormClosing);
Hope it helps.