I have a form. In that I got to show a dialog (on some circumstances) with Text and a Cancel button. I want to catch the event of that button in my form Or know if that cancel button was clicked.
How can this be done ? I believe this should be possible but can't make out how ?
From my mainForm I have BackgroundWorker. When the backgroundWorker is started I open a childForm (with a Label and a button) and when the background task is over, I close the childForm. What I want more is : when the button of childForm is clicked the ongoing task of backgroundWorker should be cancelled.
SOLUTION
In my childForm I have set CancelButton property as cancelBtn for the form. The othe code is :
private bool cancel;
public bool Cancel
{
get { return cancel; }
set { cancel = value; }
}
// Set the flag as true to indicate that Cancel button was actually pressed
private void cancelBtn_Click(object sender, EventArgs e)
{
Cancel = true;
}
In mainForm :
childDlg = new ChildDialog();
// wHILE cALLING
backgroundWorker1.RunWorkerAsync();
msg = "Connecting...";
childDlg .set(msg, "");
if (!childDlg .IsAccessible)
{
// This is caught even when the dialog is closed
if (childDlg .ShowDialog() == DialogResult.Cancel) {
if (childDlg.Cancel == true) { // Was really cancelBtn pressed
// NOW ONLY do my stuff
}
}
}
I had tried using #DeveloperX technique i.e. EventHandler in parent class, but the parent class method was nver being called. Tried a lot but couldn't success. Then tried of #RobinJ's technique and it worked. I just had to add flag to identify was really cancel button pressed or jjst windw was closed normally.
Thanks to all of you for tryig to help me out. I really appreciate your help.
Thanks
Set DialogResult property to either DialogResult.Ok or DialogResult.Cancel
Then in the parent form:
Form form = new Form();
DialogResult results = form.DialogResult;
if(results == DialogResult.Ok)
{
... make magic
}
else
{
...
}
Put this in the form that should catch the event:
frmDialog.ShowDialog();
And this in the btnCancel_Click event of the dialog:
return DialogResult.Cancel();
Sorry if I'm confusing VB and C# here, but it's pretty much the same.
Simply you can create an event for the form that shows the dialog
and handle this event in parent form
in case the user clicks on ok fire event with specefic parameter and for cancel another parameter (such dialogresult.cancel)
an pseudo implementation can be like this
public class FormChild : System.Windows.Forms.Form
{
public event EventHandler DialogCanceled;
public event EventHandler DialogConfirmed;
public void ShowDialog()
{
using (var dialogForm = new FormDialog())
{
if (dialogForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (DialogConfirmed != null)
DialogConfirmed(this,new EventArgs());
}
else
{
if (DialogCanceled != null)
DialogCanceled(this,new EventArgs());
}
}
}
}
public class ParentForm : System.Windows.Forms.Form
{
public void callChild()
{
using (var f = new FormChild())
{
f.DialogCanceled += new EventHandler(f_DialogCanceled);
f.DialogConfirmed += new EventHandler(f_DialogConfirmed);
f.ShowDialog();
}
}
void f_DialogConfirmed(object sender, EventArgs e)
{
throw new NotImplementedException();
}
void f_DialogCanceled(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
You should be using the ShowDialog method on the form you need to show as a dialog and then use the DialogResult property to communicate to the parent form the result of the dialog operation.
This way you handle the button click on the form that owns the button but set the DialogResult to DialogResult.Cancel to specify that the user pressed the cancel button.
A dialog is usually a blocking event, where eventhandling by the parent form would make no sense at all.
If it isn't a modal dialog, you can always create one or several public events in the popup form, that are triggered when the buttons are clicked. These events can then be caught by the parent form.
Don't expose your buttons to the parent form, it would be terrible oo-programming.
Use the following:
Form form = new Form();
switch (form.ShowDialog())
{
case DialogResult.Ok:
{
....
Break;
}
case DialogResult.Cancel:
{
....
Break;
}
}
Set the Form.AcceptButton and Form.CancelButton properties to the appropriate buttons.
Refer to the following:
Form.ShowDialog Method
DialogResult Enumeration
Form.AcceptButton Property
Form.CancelButton Property
Related
I want to reload the current form (not the main form) whenever both of the radio buttons are unchecked. I did this but it won't work.
StreamWriter sw;
using (sw = File.CreateText(path))
{
if (OnewayRadio.Checked == true)
{
sw.WriteLine("One Way Ticket");
}
else if (RoundRadio.Checked == true)
{
sw.WriteLine("Round Trip");
}
else
{
MessageBox.Show("You have not selected your type of trip!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
sw.Close();
File.Delete(path);
sw = File.CreateText(path);
}
sw.WriteLine("Name: " + name.Text);
sw.WriteLine("Number: " + number.Text);
}
A common practice is to open a form using ShowDialog
When your code in the form completes executing it will set a public DialogResult
The caller can then read the DialogResult and take any necessary action.
In your case, you can set the DialogResult to Retry for this specific instance. The opener can then run a loop and continue to show the form again while ShowDialog() == DialogResult.Retry
Form2 testDialog = new Form2();
// Show testDialog as a modal dialog and determine if DialogResult = OK.
while (testDialog.ShowDialog() == DialogResult. Retry)
{
testDialog.Dispose();
testDialog = null;
testDialog = new Form2();
}
The answer here assumes that the form to reopen is allowed to be modal. That is not always the case. I ran into the issue when making a form non-modal instead of modal.
Use .Hide() instead of .Close().
Place the Hide in the FormClosing() event like so,
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Hide();
e.Cancel = true;
}
After the form is "closed" in this way, a next call to Show() will have no issue.
In my case, some actions after closing the form had to be executed. If you normally open in Modal state, the ShowDialog() will return when the form is closed, like so
{
// ..
form1.ShowDialog();
OperationsAfterClose(form1);
// ..
}
A non-modal call form.Show() will return immediately. So any epilogue like my OperationsAfterClose() would be called immediately.
I used a delegate to move the action, as follows,
public delegate void OnFormHide(FrmMapFerryAnalysisSpec2 f);
public partial class Form1 : Form
{
public OnFormHide OnForm1Hide = null;
// ..
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (OnForm1Hide!=null) OnForm1Hide (this); // call the delegate
Hide();
e.Cancel = true;
}
// ..
}
In the calling form I can now pass OperationsAfterClose() as a delegate,
{
// ..
form1.Show();
form1.OnForm1Hide = OperationsAfterClose; // set the delegate
// ..
}
NOTES:
in order to use this safely, the form1 handle should exist and must not be created multiple times !
Also in most applications, the form may only open once. To do that, easiest is to introduce a IsOpenForm1 boolean in the calling form.
I am learning about Forms and somehow can't figure out what's the problem with this code that when I want to press either button with Dialog.Result.Yes or button with Dialog.Result.No in Form2 to keep the Form2 open it anyway closes after clicking on one of them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_MouseClick(object sender, MouseEventArgs e)
{
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
this.DialogResult = DialogResult.None;
}
else if (Form2.DialogResult == DialogResult.No)
{
DialogResult = DialogResult.None;
}
}
}
Thanks for any advice
If you want to keep the Form2 open, you need to set the DialogResult property of Form2, not the DialogResult property of Form1.
You need to move this logic in the button on Form2 that close the Form2
So, suppose to have a button on Formular form class named buttonOK and its property DialogResult is set to DialogResult.OK.
Then in that class code you write the event handler for the button click event (not the MouseClick event)
private void buttonOK_Click(object sender, MouseEventArgs e)
{
// Perform some logic to validate the inputs and if something is wrong return false
if(SomeLogicToAcceptTheForm() == false)
{
// Inform the user of the error
MessageBox.Show("Your input is not valid");
// Stop the closing process of this Formular instance
this.DialogResult = DialogResult.None;
}
// If your logic accepts the input, then the code continue at this point
// This will cause the form to exit from the ShowDialog call
// and you can read the current form DialogResult value.
}
EDIT
To better understand this flow you should consider that, BEFORE calling the event handler for the button click event, the forms engine sets the Form's DialogResult property from the value present in the button's DialogResult property. So, if your validation turns out to be correct you don't need to do anything and the form closes returning DialogResult.OK (or whatever you have put in the Button's DialogResult property).
The act of setting a DialogResult will cause the Form to close returning that result to the Form that created the instance, that way it can check the result and take the appropriate action. In your case since you want to keep the second form open you either need to not assign the DialogResult.No to the button and do like Steve suggests or you can intercept the Form's FormClosing event, test for the DialogResult if DialogResult.No set to None and cancel the Closing of the Form.
Though I would suggest not using a DialogResult if you are wanting to keep the Form Open.
public Form2()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.No;
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Yes;
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.DialogResult == DialogResult.No)
{
DialogResult = DialogResult.None;
e.Cancel = true;
}
}
In the Form2 pick control for assigning respective dialog result.
Same DialogResult will be produced by the Form2 control if you click on it.
Example in Form2:
button1.DialogResult = DialogResult.Yes;
button2.DialogResult = DialogResult.No;
Now pressing any of these buttons should close the Form2.
If you want to restrict closing on button1 and button2. Following changes in the Click event are required:
private void button1_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.None;
}
Form1:
In result you could see what is result, by looking into Form2.DialogResult. You can do this as you get results from Form2 dialog:
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
//
}
else if (Form2.DialogResult == DialogResult.No)
{
//
}
On any windows form displayed as modal (using ShowDialog()), the act of setting DialogResult will cause to hide the modal form and return control to calling code. Read Remarks from this page of MSDN
If you wish to show your form again, you can do the following:
private void button1_MouseClick(object sender, MouseEventArgs e)
{
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
Form2.DialogResult = DialogResult.None;
}
else if (Form2.DialogResult == DialogResult.No)
{
Form2.DialogResult = DialogResult.None;
}
Form2.Show(); // or Form2.ShowDialog()
}
I have a dialog that I want to prevent from closing when the OK button is clicked, but it returns, and that even if the AcceptButton property is set to none instead of my OK button. What is the best way to stop it from closing?
In fact you are changing the wrong property. You certainly do want AcceptButton to be the OK button. This property determines which is the default button in Windows terms. That is the button which is pressed when you hit ENTER on your keyboard. By changing AcceptButton you are simply breaking the keyboard interface to your dialog. You are not influencing in any way what happens when the button is pressed.
What you need to do is set the DialogResult property of your button to DialogResult.None since that's what determines whether or not a button press closes the form. Then, inside the button's click handler you need to decide how to respond to the button press. I expect that, if the validation of the dialog is successful, you should close the dialog by setting the form's DialogResult property. For example
private void OKbuttonClick(object sender, EventArgs e)
{
if (this.CanClose())
this.DialogResult = DialogResult.OK;
}
The best way to stop this behavior is changing the DialogResult property of your OK button to DialogResult.None in the property window at design time.
Also, If you have already some code in the click event of the OK button you could change the form DialogResult.
private void comOK_Click(object sender, EventArgs e)
{
// your code .....
// Usually this kind of processing is the consequence of some validation check that failed
// so probably you want something like this
if(MyValidationCheck() == false)
{
// show a message to the user and then stop the form closing with
this.DialogResult = DialogResult.None;
}
}
You need to remove the DialogResult of the button itself as well, in the properties window on the button set it to None.
http://msdn.microsoft.com/en-us/library/system.windows.forms.button.dialogresult.aspx
If the DialogResult for this property is set to anything other than
None, and if the parent form was displayed through the ShowDialog
method, clicking the button closes the parent form without your having
to hook up any events.
Obviously, now your button won't do anything so you will need to register a handler for the Click event.
The best practice is to actually set the Ok button to be disabled rather than not respond to user input.
The DialogResult property SHOULD be set to Ok or Yes depending on the form and the AcceptButton should also be linked to Ok.
I normally create a function on all dialogs and call it whenever the user interacts with the data.
void RefreshControls()
{
button.Enabled = this.ValidateInput();
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form2 fLogin = new Form2();
if (fLogin.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form1());
}
else
{
Application.Exit();
}
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void btnKlik_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
I'm opening a modal dialog asking the user to fill certain fields.
if(dlgUserDetail.ShowDialog() == DialogResult.OK)
{
}
On click of OK, the control comes to the parent form where I'm validating the user input.
If the validation fails, I wanted to keep the dialog to be open with the old values. Since it is modal dialog, the form gets closed.
It seems to be a common problem as I see many discussion on net, but nowhere I was able to find a solution.
Please let me know how to solve this problem. Thanks.
Regards
ArunDhaJ
If it is your dialog you could add a CancelEventArgs event called Validate or InputOk (similar to FileOk in OpenFileDialog) and have your main form check the input in a method. Before calling DialogResult = DialogResult.OK in your dialog, you add a ´onValidate` call to check if the input is valid.
{
// dialog
{
if (onValidate()) {
DialogResult = DialogResult.OK;
}
}
private bool onValidate() {
CancelEventHandler handler = Validate;
if (handler == null) {
return true;
}
CancelEventArgs args = new CancelEventArgs();
handler(this, args);
return args.Cancel;
}
}
{
// form
{
dlgUserDetail.Validate += valid;
if(dlgUserDetail.ShowDialog() == DialogResult.OK) { }
}
private void valid(object sender, CancelEventArgs e) {
// check input and set
e.Cancel = true;
// if not valid
}
}
One solution is to put validate logic into dlgUserDetail form and invoke it on OnClosing event. If the validation failed then prevent the form from closing.
I have a dialog that I show with <class>.ShowDialog(). It has an OK button and a Cancel button; the OK button also has an event handler.
I want to do some input validation in the event handler and, if it fails, notify the user with a message box and prevent the dialog from closing. I don't know how to do the last part (preventing the close).
You can cancel closing by setting the Form's DialogResult to DialogResult.None.
An example where button1 is the AcceptButton:
private void button1_Click(object sender, EventArgs e) {
if (!validate())
this.DialogResult = DialogResult.None;
}
When the user clicks button1 and the validate method returns false, the form will not be closed.
Given that you've specified you want a pop error dialog, one way of doing this is to move your validation into a OnClosing event handler. In this example the form close is a aborted if the user answers yes to the question in the dialog.
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Determine if text has changed in the textbox by comparing to original text.
if (textBox1.Text != strMyOriginalText)
{
// Display a MsgBox asking the user to save changes or abort.
if(MessageBox.Show("Do you want to save changes to your text?", "My Application",
MessageBoxButtons.YesNo) == DialogResult.Yes)
{
// Cancel the Closing event from closing the form.
e.Cancel = true;
// Call method to save file...
}
}
}
By setting e.Cancel = true you will prevent the form from closing.
However, it would be a better design/user experience to display the validation errors inline (via highlighting the offending fields in some way, displaying tooltips, etc.) and prevent the user from selecting the OK button in the first place.
Don't use the FormClosing event for this, you'll want to allow the user to dismiss the dialog with either Cancel or clicking the X. Simply implement the OK button's Click event handler and don't close until you are happy:
private void btnOk_Click(object sender, EventArgs e) {
if (ValidateControls())
this.DialogResult = DialogResult.OK;
}
Where "ValidateControls" is your validation logic. Return false if there's something wrong.
You can catch FormClosing an there force the form to remain opened.
use the Cancel property of the event argument object for that.
e.Cancel = true;
and it should stop your form from closing.
This doesn't directly answer your question (other already have), but from a usability point of view, I would prefer the offending button be disabled while the input is not valid.
Use this code:
private void btnOk_Click(object sender, EventArgs e) {
if (ValidateControls())
this.DialogResult = DialogResult.OK;
}
The problem of it is that the user has to clic two times the buttons for closing the forms;
Just add one line in the event function
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
this->DialogResult = System::Windows::Forms::DialogResult::None;
}
I wish I had time to find a better example, but you would be much better off using the existing windows forms validation techniques to do this.
http://msdn.microsoft.com/en-us/library/ms229603.aspx
void SaveInfo()
{
blnCanCloseForm = false;
Vosol[] vs = getAdd2DBVosol();
if (DGError.RowCount > 0)
return;
Thread myThread = new Thread(() =>
{
this.Invoke((MethodInvoker)delegate {
picLoad.Visible = true;
lblProcces.Text = "Saving ...";
});
int intError = setAdd2DBVsosol(vs);
Action action = (() =>
{
if (intError > 0)
{
objVosolError = objVosolError.Where(c => c != null).ToArray();
DGError.DataSource = objVosolError;// dtErrorDup.DefaultView;
DGError.Refresh();
DGError.Show();
lblMSG.Text = "Check Errors...";
}
else
{
MessageBox.Show("Saved All Records...");
blnCanCloseForm = true;
this.DialogResult = DialogResult.OK;
this.Close();
}
});
this.Invoke((MethodInvoker)delegate {
picLoad.Visible = false;
lblProcces.Text = "";
});
this.BeginInvoke(action);
});
myThread.Start();
}
void frmExcellImportInfo_FormClosing(object s, FormClosingEventArgs e)
{
if (!blnCanCloseForm)
e.Cancel = true;
}
You can probably check the form before the users hits the OK button. If that's not an option, then open a message box saying something is wrong and re-open the form with the previous state.