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()
}
Related
This question already has an answer here:
Interaction between forms — How to change a control of a form from another form?
(1 answer)
Closed 4 years ago.
Sorry, I'm a C# beginner
I am trying to make a button on Form 4 that will make change a property of an object in Form 3.
This case, every time I press button 1 on Form 4, the label on Form 3 will say that "You pressed button 1", Same thing on the button 2.
I added this on Form 4.
public partial class Form4 : Form
{
public bool buttonchecked;
private void button1_Click_1(object sender, EventArgs e)
{
buttonchecked = true;
}
private void button2_Click_1(object sender, EventArgs e)
{
buttonchecked = false;
}
And this is what i put on Form 3:
public void label2_Click(object sender, EventArgs e)
{
Form4 form4 = new Form4(); //add
if (form4.buttonchecked == true)
{
label2.Text = "You pressed button 1";
}
else
{
label2.Text = "You pressed button2";
My label2 text is always set to "You pressed button2" but I didn't
I added a code that closes the current form and Opens the other form, maybe this is causing the problem?
this is from the Form 3
this.Hide();
Form4 f4 = new Form4();
f4.ShowDialog();
and this is from the Form 4
this.Hide();
Form3 frm3 = new Form3();
frm3.ShowDialog();
Is there anything something I'm doing wrong?
There are a few issues with your code:
On Form3, why are you handling the label2_click button? This event is fired when you click on a label. If the Text property of your label is an empty string, you won't even see the label in order to be able to click it.
This code:
Form4 form4 = new Form4();
if (form4.buttonchecked == true)
// etc
is not logically correct, because you are creating a Form4 instance and then you're checking the value of it's public field (buttonchecked) without displaying the form. The default value of a boolean variable is false, so the control will always hit the else branch. That's the reason you're always getting the "You pressed button2" message.
One correct way to do this using your code is the following:
On Form3:
var form4 = new Form4();
var result = form4.ShowDialog();
if (result == DialogResult.OK)
{
label2.Text = "You pressed button 1";
}
else
{
label2.Text = "You pressed button 2";
}
On Form4:
public partial class Form4 : Form
{
public bool buttonchecked;
private void button1_Click_1(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void button2_Click_1(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
The ShowDialog() method will display the Form4 and will block the Form3 execution. On Form4 you set a DialogResult based on the button you pressed and you return that result to the calling form (Form3). Based on that result, you can take a decision.
That solution will do the job, but it has one issue: you can't play with both forms in parallel because of the Dialog constraint (when you open the Form4 from Form3, you have to close it in order to reach Form3 again, you can't play with both of them in the same time).
So here's a new (clean) solution that solves this problem:
On Form3 in Designer Mode, click on the label2 -> Properties -> Modifiers -> Public. In that way you can access the label2 from other forms.
On Form4, place the follwing code:
public partial class Form4 : Form
{
private void button1_Click_1(object sender, EventArgs e)
{
var form3 = Application.OpenForms["Form3"];
form3.label2.Text = "You pressed button 1";
}
private void button2_Click_1(object sender, EventArgs e)
{
var form3 = Application.OpenForms["Form3"];
form3.label2.Text = "You pressed button 2";
}
}
Note: on that solution, Form3 needs to be open before Form4, otherwise Application.OpenForms["Form3"] will return null or it will throw an exception.
If you have any further issues, don't hesitate to leave a comment.
I'm writing a WinForm desktop application. In the main form, the user clicks on a button which calls another form for the user to submit data to. At the end of this submission process, the user clicks on a "Save" menu item to close the subform.
This is the code for the subform calling:
private void btnSubmit_Click(object sender, EventArgs e)
{
// code for setting myFormArgs
myForm form = new myForm(myFormArgs);
form.ShowDialog();
// the user clicked "Yes" on a "Confirm" MessageBox
if (form.DialogResult == DialogResult.Yes)
{
// code for saving data
form.Dispose();
}
}
and this is the code for the "Save" menu item in the subform:
private void menuSave_Click(object sender, EventArgs e)
{
string message, title;
MessageBoxIcon icon;
MessageBoxButtons buttons;
if(DataSubmitted)
{
if(ValidData)
{
message = "Confirm?";
title = "Select an action";
icon = MessageBoxIcon.Information;
buttons = MessageBoxButtons.YesNo;
}
else
{
message = "Incomplete data";
title = "Error";
icon = MessageBoxIcon.Error;
buttons = MessageBoxButtons.OK;
}
}
else
{
message = "No data submitted";
title = "Error";
icon = MessageBoxIcon.Error;
buttons = MessageBoxButtons.OK;
}
this.DialogResult = MessageBox.Show(message, title, buttons, icon);
if (this.DialogResult == DialogResult.Yes) this.Close();
else this.OnFormClosing(new FormClosingEventArgs(CloseReason.None, true));
}
The problem is that the code will always get back to the calling method, thus closing (maybe just hiding?) the sub-form, even if the this.Close() method isn't called.
Thanks in advance.
you should not make a new event instance, those are things you would want to avoid
instead try:
DialogResult dialogResult = MessageBox.Show("Sure", "Some Title",
MessageBoxButtons.YesNo);
if(dialogResult == DialogResult.Yes)
{
Close();
}
Events are supposed to occur automatically, so 'OnFormClosing' will raise when the form will close.
also i recommend to use this.Close instead of Dispose
Form.Close() sends the proper Windows messages to shut down the win32 window. During that process, if the form was not shown modally, Dispose is called on the form. Disposing the form frees up the unmanaged resources that the form is holding onto.
for more organized code,
try making an instance of the form from the main form
and handle the dialog result like this:
using (SubForm form = new SubForm())
{
DialogResult dr = form.ShowDialog();
if(dr == DialogResult.Yes)
{
string studdToSave= form.StuffToSave;
SaveToFile(studdToSave);
}
}
I find it strange that you want to close the form when the user just wants to save the data. :)
Save should not close your form.
When you close the form, you should verify if there are unsaved changes.
If there are, ask the user the question if he wants to save his changes before closing and offer him the options Yes, No and Cancel, where Cancel means 'cancel closing the form'.
Depending on wether the user clicked Yes or No, you should or shouldn't save the changes.
If the user clicked cancel, you should cancel closing the form by having an event for the FormClosing event. This event allows you to cancel closing the form.
private void btnClose_Click(object sender, EventArgs e)
{
if (unsavedChanges)
{
var result = MessageBox.Show("Save changes?", "unsaved changes", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Yes)
{
SaveChanges();
}
if (result == DialogResult.Cancel)
{
cancelClose = true;
}
this.Close();
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = cancelClose;
cancelClose = false;
}
The code above is usefull when 'Form2' is not a modal form.
If you want Form2 to be shown modal, the code above will work as well. However, you can also use the DialogResult proprety of the Form in that case:
private void btnClose_Click(object sender, EventArgs e)
{
if (unsavedChanges)
{
var result = MessageBox.Show("Save changes?", "unsaved changes", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Yes)
{
SaveChanges();
}
if (result == DialogResult.Cancel)
{
result = DialogResult.None;
}
this.DialogResult = result;
}
}
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 following code now:
var picker = new DateTimePicker();
var form = new Form();
form.Controls.Add(picker);
var result = form.ShowDialog();
if (result == DialogResult.OK)
{
//Can´t acces this
}
if (result == DialogResult.Cancel)
{
//Do when Form closed
}
When the form appears, there´s only picker on it, no buttons. Now I can only acces result == DialogResult.Cancel when I close the form. What I need to do to access branch with result == DialogResult.OK
You can add 2 buttons OK and Cancel onto your form and handle the Click events properly. The point is you have to use the DialogResult property to close your form instead of the Close() method, like this:
//Click event handler for your OK button
private void OK_Click(object sender, EventArgs e){
DialogResult = DialogResult.OK;
}
//Click event handler for your Cancel button
private void Cancel_Click(object sender, EventArgs e){
DialogResult = DialogResult.Cancel;
}
Or simply you can use the DialogResult property of a Button (no need to add code to Click event handler):
buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
NOTE: All the above things work only if you show your form using ShowDialog(). Otherwise, you have to close your form manually
I have some custom made dialog that have on it Set Button , I want when i exit from newBlockForm.ShowDialog(this); to get the dialog result if the user pressed on that button or not .
Like i would do in winforms dialog
if(MessageBox.Show("Exit?", "Close UP",
MessageBoxButtons.YesNo)== DialogResult.Yes)
Any idea how i do so ?
You can use the DialogResult Property of the Button on your Dialog form and set it to DialogResult Enumeration like:
//in your dialog form
button1.DialogResult = DialogResult.OK;
then in your main form :
//Create an instance of your dialog form
Form2 testDialog = new Form2();
// Show testDialog as a modal dialog and determine if DialogResult = OK.
if (testDialog.ShowDialog(this) == DialogResult.OK)
{
//do processing
}
else
{
//do processing
}
Map the AcceptButton property on the Form to Set button in the designer.
Or in the Set button click handler you could set some value.
private void HandleOnSetButtonClick(object sender, EventArgs e)
{
this.IsSetClicked = true;
this.Close();
//or
this.DialogResult = System.Windows.Forms.DialogResult.OK;
this.Close();
}
public Boolean IsSetClicked
{
get;
private set;
}
ShowDialog method returns a DialogResult by itself which you can set automatically by setting the DialogResult of the buttons in question in your form designer.