Calling PerformClick cancels closing event - c#

Something strange is happening in my WinForms app (and with strange things it's normally my fault).
I've got a FormClosing event that will check whether any changes has been made on the form that has not been saved.
If the user confirm to save the changes, I will call the Save button's click event. However, even if I remove all the logic in the OnClick event, the form stays open, and I have to close it again before it closes.
If I skip the line buttonSave.PerformClick(); then the form closes properly.
Why will entering the click event, cancel the close? Any work around?
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
//Check if there changes were made on the form
//Prompt user to save
if (confirmSave)
buttonSave.PerformClick();
}
private void buttonSave_Click(object sender, EventArgs e)
{
//Everything in here commented out.
}

Just call the event instead of PerformClick.
PerformClick probably executes more code that makes the form stop closing. Like showing that the button is clicked, the sound etc.
So change PerformClick to buttonSave_Click. So it will just do the save function, without doing anything with the button itself.

Related

Open .net windows form after event finishes

I'm having a Windows Mobile CE application written in C# with .Net CF.
Consider i have 2 forms in my application:
List of objects (has a listview)
Details page (should appear when something is selected in previous listview)
Currently i'm attaching callback to listview's SelectedIndexChanged event, and open a new form there.
New form opens okay (in the midde of the event callback), but when i close the form(this.Close()), then the list page isn't clickable first time, after the first click UI is interactable again.
Also the the ListViewItem clicked at first step doesn't get selected(blue background).
Here's a short (12s) video showing this problem: http://take.ms/urkme
As you see from the video, after coming back from details screen, refresh button doesn't click on the first click..
I'm showing the details form like so:
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
(new FormDetails()).ShowDialog();
}
Is there any way to show the details form after event finishes, or am i doing it completely wrong?
PS! Tried the same with a Button and it's click event, then all worked nicely..
As I know ListView's SelectedIndexChanged event fired twice on almost case not like Button's Click event which fired once, this maybe what cause that weird interaction. Maybe try changing to ItemSelectionChanged event as suggested in here.
Your problem is caused by using the SelectedIndexChanged event. When you select an item in your list you'll set the SelectedIndex, if you select the same item again the index won't be changed so you'll never call the event.
You could use the Click event to trigger the wanted response.
Here is an example:
private void listView1_Click(object sender, EventArgs e)
{
var firstSelectedItem = listView1.SelectedItems[0]; //This is your selected item.
//do stuff
}
When you use ShowDialog() you open a form in modal mode. All further processing of following code will not take place until the modal form is closed or returns a DialogResult.
Better use a modeless form using .Show().
private void listView_SelectedIndexChanged(object sender, EventArgs e)
{
(new FormDetails()).Show(); //will not stop processing of events in mainForm
}
If the new FormDetails is finished, it can use a simple Hide or Close to bring up the main form to foreground.
Remember that the main form is still there and will not wait for the FormDetails being closed (as it is a modeless dialog).

Button clicked event not triggering after lost focus event

I have a Winforms c# form with some comboBoxes , cancel and save buttons that work fine.
I now need to capture when the user has finished entering text into a comboBox.
I add an empty ( for now) lostFocus (or Leave) event to the combbox , which triggers fine. However if the cause of that event was a cancel or save button press , the corresponding event is no longer triggered. These buttons still work fine if pressed at other times.
Should these two event be firing in sequence or is there some better way to capture completed text entry?
The Leave and/or LoseFocus events do not get triggered because you do not leave the combobox and because it doesn't lose focus when you press Enter or Escape.
Therefore the best way is to add the function you are triggering in the LoseFocus event, also to the Button click events of the Cancel- and the Accept-Buttons.
Adding a call to the leave event itself: comboBox1.Leave(null, null); would be the simplest way.
To make sure that the function is called only once, I check who has focus in the ButtonClick events:
private void acceptButton_Click(object sender, EventArgs e)
{
if (comboBox1.ContainsFocus) comboBox1_Leave(acceptButton, null);
// do accept stuff here..
}
private void cancelButton_Click(object sender, EventArgs e)
{
if (comboBox1.ContainsFocus) comboBox1_Leave(cancelButton, null);
// do cancel stuff here..
}
private void comboBox1_Leave(object sender, EventArgs e)
{
// do leave stuff here..
Console.WriteLine(sender);
}
I also pass in the Button so you could check the sender to see how the Leave was triggered..
I'm answering my own question here as I feel it might be useful to other newbies.
The breakpoint I had set in my empty lostFocus event was stopping button click event from occurring. When I removed the breakpoint the problem went away.
However when I added code to my lostFocus event, a form redraw was sometimes moving the buttons and preventing their events from firing. To solve this problem I adapted TaWs very useful answer and fired the button event from within the lostFocus event.
private void comboBox1_LostFocus(object sender, EventArgs e)
{
bool saving = btnSave.ContainsFocus;
// form redraw stuff here..
if (saving)
btnSave_Click(btnSave, null);
}

Close form using the cross button

I'm working on a C# project. I need to do the following but I'm not really experienced and I can't find it on the Internet.
I want to do an action when the user clicks on the cross button (for closing one form). I mean, if the user clicks on the "X" button on the top right of the form I want to use a method that deletes one file.
I just want to know the code for noticing that the user clicked on the "X" (close) button. I hope you guys understand my question. Thank you so much!!
I don't think it's user friendly to delete something on closing a form (especially as the 'X' button is understood as the close button by everybody who uses a computer), but you can override the OnFormClosing method of a form. Something like this:
// this will also close the form
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (e.CloseReason == CloseReason.WindowsShutDown) return;
// Do some stuff here (delete the file or whatever)
}
If you want to alter the behavior so bad that the form won't close on pressing 'X', you could do sth like
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
// some stuff here...
}
Which is very nasty IMO
You have to handle FormClosing event:
The FormClosing event occurs as the form is being closed. When a form
is closed, it is disposed, releasing all resources associated with the
form. If you cancel this event, the form remains opened. To cancel the
closure of a form, set the Cancel property of the FormClosingEventArgs
passed to your event handler to true.

FormClosing with CloseReason = UserClosing doesn't work expectedly?

I have a main form, in the class of this form, I declare another form. This form lives with the main form until the main form is unloaded. There is a button on the main form, clicking this button will show the member form (I mentioned above). I want to prevent the member form from closing when user closes that form and I added the following FormClosing event handler for that form:
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e) {
if(e.CloseReason == CloseReason.UserClosing){
e.Cancel = true;
Hide();
}
}
That works OK for that form. However if user closes the main form, this form is not closed, and it's hidden somewhere making my application seem to run silently. I want this form also to be closed. This is very simple by adding some FormClosed event handler for my main form to close the member form manually. Closing it manually is OK, but why do I have to do that? It seems that when user closes the main form, the FormClosing event of the member form is fired with a parameter FormClosingEventArgs passed in and the CloseReason is the same as the CloseReason of the main form (which is UserClosing). I don't understand this, I thought the CloseReason of the form is UserClosing only when user clicks on the X button, I thought the CloseReason for my member form is something like "MainFormClosing".
Is there some way to close the member form automatically as by default?
UPDATE
Here is the method showing the member form (showing it as a dialog):
private void ShowMemberForm_Click(object sender, EventArgs e){
memberForm.ShowDialog();
}
But I don't think this matters, because when I load my main form, even I don't need to click on the ShowMemberForm button, and try closing my main form first, it doesn't still close the member form.
Thanks!
UPDATE
There is something strange here, I've tried commenting out the line e.Cancel = true, or even all the FormClosing event handler and the problem is still there. This is so strange, it works OK before, I've just added the member form and this form relates to some Thread handling, but the thread starts only when a button on the member form is clicked. I didn't click that button.
What I have done in the past is set a flag when programatically closing
so in the MemberForm
private bool _ForceClose = false;
public void ForceClose()
{
_ForceClose = true;
this.Close();
}
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(!_ForceClose)
{
e.Cancel = true;
Hide();
}
}
Then in your MainForm you can call
memberForm.ForceClose();
From within your MainForms FormClosing method or from your MainForms Dispose() or Deconstructor.
It's low tech, but it works. Im not sure if you should put _ForceClose = true in your MemberForm's Dispose method, i'm fairly certain when it gets there its already been closed BUT it couldn't really hurt.

c# WinForms form still closes after setting e.Cancel = true in Form_FormClosing event

This is the code in question:
private void FormAccounting_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.FormAccountingLocation = this.Location;
Properties.Settings.Default.Save();
if (IsEditing)
{
MessageBox.Show("Please save or cancel open transactions before closing the accounting window.", "Open Transactions", MessageBoxButtons.OK, MessageBoxIcon.Information);
e.Cancel = true;
}
}
I've added breakpoints to the e.Cancel = true; line to ensure it's being executed.
The form closes immediately after clicking Ok.
Here's the code that calls FormAccounting:
private void buttonAccounts_Click(object sender, EventArgs e)
{
FormAccounting NewFormAccounting = new FormAccounting();
NewFormAccounting.Show();
}
Canceling the form close event works to prevent:
User closing the form
Application.Exit from exiting the application
Code from calling Form.Close on the form
But it does not work to prevent:
User closing application's main form
Code calling Form.Dispose on the form
Code calling Form.Close on the application's main window
The last 3 cases don't even trigger the form close event on the non-main form, so the form goes away without a chance to cancel it. Perhaps your application is causing the form to first close in one of the first 3 ways, which triggers the event, and then in one of the second 3 ways (or something similar), which does not trigger the event and forces the form closed anyway.
Edit:
Add this function to your form's code and it will allow you to review in the debugger what the call stack looks like when your window is getting closed so you can see what is actually causing it:
protected override void DestroyHandle()
{
System.Diagnostics.Debugger.Break();
base.DestroyHandle();
}

Categories

Resources