I am validating input on textboxes on the FormClosing event of my Form and if the user decides to cancel closing, I set e.Cancel = true so as to stop the FormClosing event. I then try to set focus to the first textbox but this is not working.
private void AddDriver_Window_FormClosing(object sender, FormClosingEventArgs e)
{
if (this._Cancel(sender, e))
{
e.Cancel = true;
this.textboxFirstName.Focus();
}
}
If you are interested in seeing the ._Cancel method I asked an unrelated question earlier.
I tried this one Check this is it work for you..
private void AddDriver_Window_FormClosing(object sender, FormClosingEventArgs e)
{
if( DialogResult.Cancel == MessageBox.Show("Do you want to exit programm","Alert",MessageBoxButtons.OKCancel))
{
e.Cancel = true;
textBox1.Focus();
}
}
this will popup a message box and if click cancel then automatically focus on the textbox1.
I have a form which I use as a modal dialog box for data entry. When the user clicks on the OK button on the form, I want the button handler to perform data validations and if there is any error the form should reload/redisplay itself instead of returning to the caller. Is this possible?
Caller code:
DatasetProperties propsWindow = new DatasetProperties();
if (propsWindows.ShowDialog() == DialogResult.Cancel)
return;
// Do other stuffs here
Form code:
public partial class DatasetProperties : Form
{
// Constructor here
// OK button handler
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
if (errorsFound)
{
// How to reload/redisplay the form without return to caller?????
}
}
}
Thanks for any help,
Don't let the user close the form without validation.
Use the FormClosing event. Here's an example. In lieu of the messageBox, include your validation code. If it doesn't validate, e.cancel = true.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Are you sure you want to cancel without saving any changes?", "Confirm Cancel", MessageBoxButtons.YesNo) != DialogResult.Yes)
e.Cancel = true;
}
You can set the Form.DialogResult inside your DatasetProperties.btnOK_Click method to DialogResult.None, this way your DatasetProperties form will not return to the caller Form ('close').
// OK button handler
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
if (errorsFound)
{
this.DialogResult = System.Windows.Forms.DialogResult.None;
// How to reload/redisplay the form without return to caller?????
}
}
This way you can 'stay' in your DatasetProperties form as long as you have errors.
From the msdn, when the DialogResult Enumeration is set to None Nothing is returned from the dialog box. This means that the modal dialog continues running.
as user1646737 mentioned you can use FormClosing event like this:
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
Close();
}
Event:
private void DatasetProperties_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = errorsFound;
}
I have a form which contains a close button (there are many control in the form, but I am concerning about the close event) and a save button.
If a form have value in certain text box (say TextBox1),
Then I want to validate that the save button is clicked before closing the form (whether close button or the 'X' button at top is pressed).
But if there is no value in that text box or the form is just initialized and user just want to close the form, it simply closes the form. How to perform this validation.
I would follow the pattern of 99% of windows applications: allow to close a window, but ask to save changes if there are any. Here is a simple implementation of that pattern:
private bool _hasChanges;
private void textBox1_TextChanged(object sender, EventArgs e)
{
this._hasChanges = true;
}
private void form_FormClosing(object sender, FormClosingEventArgs e)
{
if (this._hasChanges)
{
var dialogResult = MessageBox.Show("Save changes?", "Confirm", MessageBoxButtons.YesNoCancel);
switch (dialogResult)
{
case DialogResult.Yes:
this.Save();
break;
case DialogResult.No:
this._hasChanges = false;
break;
}
e.Cancel = this._hasChanges;
}
}
private void Save()
{
// Save
this._hasChanges = false;
}
private void buttonSave_Click(object sender, EventArgs e)
{
this.Save();
}
private void buttonOk_Click(object sender, EventArgs e)
{
this.Close();
}
private void buttonCancel_Click(object sender, EventArgs e)
{
this._hasChanges = false;
this.Close();
}
The pivotal part is the boolean _hasChanges. If there are many controls that can cause changes this can be real pain. An alternative could be to use databinding to a class that implements INotifyPropertyChanged and subscribe to its PropertyChanged event.
Tie into the Closing Event and use your EventHandler to validate that textbox. Keep in mind that Closing occurs at the time the form is closing and (if memory servers correctly) there is a property on the eventarg that will let you cancel closing of the form. This event is raised regardless of how the request is executed.
I am working on a C#-based utility that makes use of the FormClosing event, and the event is supposed to do different things depending on whether the form was closed programatically through the form.Close(); method, or by anything else (user clicking the X, program exiting, etc.)
The FormClosingEventArgs in the FormClosing event have a property called CloseReason (of enum type CloseReason).
CloseReason could be: None, WindowShutDown, MdiFormClosing, UserClosing, TaskManagerClosing, FormOwnerClosing, ApplicationExitCall.
Ideally, there would be a way to distinguish between when the user clicks the red X, and when the Close(); method is called (through the clicking of a Continue button after other actions are performed). However, the CloseReason property in FormClosingEventArgs is set to UserClosing in both cases, so there is no way to distinguish between when the user closes the form intentially, and when the form is programmatically closed. This goes contrary to my expectation that CloseReason would equal None if the Close() method is invoked arbitrarily.
//GuideSlideReturning is an cancelable event that gets fired whenever the current "slide"-form does something to finish, be it the user clicking the Continue button or the user clicking the red X to close the window. GuideSlideReturningEventArgs contains a Result field of type GuideSlideResult, that indicates what finalizing action was performed (e.g. continue, window-close)
private void continueButton_Click(object sender, EventArgs e)
{ //handles click of Continue button
GuideSlideReturningEventArgs eventArgs = new GuideSlideReturningEventArgs(GuideSlideResult.Continue);
GuideSlideReturning(this, eventArgs);
if (!eventArgs.Cancel)
this.Close();
}
private void SingleFileSelectForm_FormClosing(object sender, FormClosingEventArgs e)
{ //handles FormClosing event
if (e.CloseReason == CloseReason.None)
return;
GuideSlideReturningEventArgs eventArgs = new GuideSlideReturningEventArgs(GuideSlideResult.Cancel);
GuideSlideReturning(this, eventArgs);
e.Cancel = eventArgs.Cancel;
}
The issue with this is that when the Close(); method is invoked after the event GuideSlideReturning finishes without being canceled, the FormClosing event handler is unable to tell that the form was closed through the method instead of being closed by the user.
What would be ideal is if I could define what the FormClosing event's FormClosingEventArgs CloseReason would be, like this:
this.Close(CloseReason.None);
Is there a way to do this? The form.Close(); method does not have any overloads that accept any parameters, so is there a variable I can set or an alternate method I can call?
Set a flag before calling close programmatically. This can be wrapped up in a private method:
private bool _programmaticClose;
// Call this instead of calling Close()
private void ShutDown()
{
_programmaticClose = true;
Close();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing();
_programmaticClose = false;
}
In MSDN I found CloseReason.UserClosing to know that the user had decided to close the form
but I guess it is the same for both clicking the X button or clicking the close button.
So how can I differentiate between these two in my code?
Thanks all.
Assuming you're asking for WinForms, you may use the FormClosing() event. The event FormClosing() is triggered any time a form is to get closed.
To detect if the user clicked either X or your CloseButton, you may get it through the sender object. Try to cast sender as a Button control, and verify perhaps for its name "CloseButton", for instance.
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if (string.Equals((sender as Button).Name, #"CloseButton"))
// Do something proper to CloseButton.
else
// Then assume that X has been clicked and act accordingly.
}
Otherwise, I have never ever needed to differentiate whether X or CloseButton was clicked, as I wanted to perform something specific on the FormClosing event, like closing all MdiChildren before closing the MDIContainerForm, or event checking for unsaved changes. Under these circumstances, we don't need, according to me, to differentiate from either buttons.
Closing by ALT+F4 will also trigger the FormClosing() event, as it sends a message to the Form that says to close. You may cancel the event by setting the
FormClosingEventArgs.Cancel = true.
In our example, this would translate to be
e.Cancel = true.
Notice the difference between the FormClosing() and the FormClosed() events.
FormClosing occurs when the form received the message to be closed, and verify whether it has something to do before it is closed.
FormClosed occurs when the form is actually closed, so after it is closed.
Does this help?
The CloseReason enumeration you found on MSDN is just for the purpose of checking whether the user closed the app, or it was due to a shutdown, or closed by the task manager, etc...
You can do different actions, according to the reason, like:
void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing)
// Prompt user to save his data
if(e.CloseReason == CloseReason.WindowsShutDown)
// Autosave and clear up ressources
}
But like you guessed, there is no difference between clicking the x button, or rightclicking the taskbar and clicking 'close', or pressing Alt F4, etc. It all ends up in a CloseReason.UserClosing reason.
The "X" button registers as DialogResult.Cancel so another option is to evaluate the DialogResult.
If you have multiple buttons on your form, you're probably already associating different DialogResults to each and this will provide you with the means to tell the difference between each button.
(Example: btnSubmit.DialogResult = DialogResult.OK, btnClose.DialogResult = Dialogresult.Abort)
public Form1()
{
InitializeComponent();
this.FormClosing += Form1_FormClosing;
}
/// <summary>
/// Override the Close Form event
/// Do something
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
//In case windows is trying to shut down, don't hold the process up
if (e.CloseReason == CloseReason.WindowsShutDown) return;
if (this.DialogResult == DialogResult.Cancel)
{
// Assume that X has been clicked and act accordingly.
// Confirm user wants to close
switch (MessageBox.Show(this, "Are you sure?", "Do you still want ... ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
//Stay on this form
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
How to detect if the form closed by click on X button or by calling Close() in code?
You cannot rely on close reason of the form closing event args, because:
if the user click X button on title bar or
close the form using Alt + F4 or
use system menu to close the form or
the form get closed by calling Close() method,
for all of above cases, the close reason will be Closed by User (CloseReason.UserClosing), which is not desired result.
To distinguish if the form closed by X button or by Close method, you can use either of the following options:
Handle WM_SYSCOMMAND and check for SC_CLOSE and set a flag.
Check the StackTrace to see if any of the frames contain Close method call.
Example 1 - Handle WM_SYSCOMMAND
public bool ClosedByXButtonOrAltF4 {get; private set;}
private const int SC_CLOSE = 0xF060;
private const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SYSCOMMAND && msg.WParam.ToInt32() == SC_CLOSE)
ClosedByXButtonOrAltF4 = true;
base.WndProc(ref msg);
}
protected override void OnShown(EventArgs e)
{
ClosedByXButtonOrAltF4 = false;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (ClosedByXButtonOrAltF4)
MessageBox.Show("Closed by X or Alt+F4");
else
MessageBox.Show("Closed by calling Close()");
}
Example 2 - Checking StackTrace
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
MessageBox.Show("Closed by calling Close()");
else
MessageBox.Show("Closed by X or Alt+F4");
}
It determines when to close the application if a form is closed (if your application is not attached to a specific form).
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0) Application.Exit();
}
I always use a Form Close method in my applications that catches alt + x from my exit Button, alt + f4 or another form closing event was initiated. All my classes have the class name defined as Private string mstrClsTitle = "grmRexcel" in this case, an Exit method that calls the Form Closing Method and a Form Closing Method. I also have a statement for the Form Closing Method - this.FormClosing = My Form Closing Form Closing method name.
The code for this:
namespace Rexcel_II
{
public partial class frmRexcel : Form
{
private string mstrClsTitle = "frmRexcel";
public frmRexcel()
{
InitializeComponent();
this.FormClosing += frmRexcel_FormClosing;
}
/// <summary>
/// Handles the Button Exit Event executed by the Exit Button Click
/// or Alt + x
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// Handles the Form Closing event
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void frmRexcel_FormClosing(object sender, FormClosingEventArgs e)
{
// ---- If windows is shutting down,
// ---- I don't want to hold up the process
if (e.CloseReason == CloseReason.WindowsShutDown) return;
{
// ---- Ok, Windows is not shutting down so
// ---- either btnExit or Alt + x or Alt + f4 has been clicked or
// ---- another form closing event was intiated
// *) Confirm user wants to close the application
switch (MessageBox.Show(this,
"Are you sure you want to close the Application?",
mstrClsTitle + ".frmRexcel_FormClosing",
MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
// ---- *) if No keep the application alive
//---- *) else close the application
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
}
}
You can try adding event handler from design like this: Open form in design view, open properties window or press F4, click event toolbar button to view events on Form object, find FormClosing event in Behavior group, and double click it.
Reference: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
namespace Test
{
public partial class Member : Form
{
public Member()
{
InitializeComponent();
}
private bool xClicked = true;
private void btnClose_Click(object sender, EventArgs e)
{
xClicked = false;
Close();
}
private void Member_FormClosing(object sender, FormClosingEventArgs e)
{
if (xClicked)
{
// user click the X
}
else
{
// user click the close button
}
}
}
}
if (this.DialogResult == DialogResult.Cancel)
{
}
else
{
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
break;
}
}
if condition will execute when user clicks 'X' or close button on form. The else can be used when user clicks Alt+f4 for any other purpose
I agree with the DialogResult-Solution as the more straight forward one.
In VB.NET however, typecast is required to get the CloseReason-Property
Private Sub MyForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
Dim eCast As System.Windows.Forms.FormClosingEventArgs
eCast = TryCast(e, System.Windows.Forms.FormClosingEventArgs)
If eCast.CloseReason = Windows.Forms.CloseReason.None Then
MsgBox("Button Pressed")
Else
MsgBox("ALT+F4 or [x] or other reason")
End If
End Sub
I also had to register the closing function inside the form's "InitializeComponent()" method:
private void InitializeComponent() {
// ...
this.FormClosing += FrmMain_FormClosing;
// ...
}
My "FormClosing" function looks similar to the given answer (https://stackoverflow.com/a/2683846/3323790):
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) {
if (e.CloseReason == CloseReason.UserClosing){
MessageBox.Show("Closed by User", "UserClosing");
}
if (e.CloseReason == CloseReason.WindowsShutDown){
MessageBox.Show("Closed by Windows shutdown", "WindowsShutDown");
}
}
One more thing to mention: There is also a "FormClosed" function which occurs after "FormClosing". To use this function, register it as shown below:
this.FormClosed += MainPage_FormClosed;
private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}
I've done something like this.
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if ((sender as Form).ActiveControl is Button)
{
//CloseButton
}
else
{
//The X has been clicked
}
}