I am writing a WinForm application in C#. There is a Form A that opens Form C on Button click. Now, I want to add a password input screen Form B before opening Form C. Only if the password entered is correct will Form C open, and otherwise, show an error message. Form B just has a TextBox control and a Verify Button control.
/*Form A*/
FormB fb;
private void BtnClick(object sender, EventArgs e) {
DialogResult result;
//fb can open once at a time
if(fb == null){
fb = new FormB();
fb.FormClosed += new FormClosedEventHandler(FormB_FormClosed);
//This seems to be not working
result = fb.ShowDialog();
}
else //FormB already open. Do nothing
return;
//Only if password entered is correct, proceed
if(result == DialogResult.Yes){ //result == cancel
//Code to open Form C //Program never reaches here
}
}
//Upon closing FormB, reset it to null
private void FormB_FormClosed(object sender, FormClosedEventArgs e){
if(fb != null)
fb = null;
}
/* Form B */
private const string password = "xxxyyyzzz";
private void BtnPW_Click(object sender, EventArgs e){
bool result = Verify();
if(result){
BtnPW.DialogResult = DialogResult.Yes;
}
else{
MessageBox.Show("Error: Incorrect password");
BtnPW.DialogResult = DialogResult.No;
}
this.Close(); //Added
}
private bool Verify(){
if(TxtBox.Text == password)
return true;
else
return false;
}
Can someone tell me what is wrong with this code? It never reaches the second if statement in Form A.
Edit: Even if I enter the correct password and hit the button on Form B, result in Form A gets "DialogResult.Cancel`.
If you call the Form.Close method, then the DialogResult property of that form is set to DialogResult.Cancel even if you have set it to something else. To HIDE a form opened modally you just need to set the form's DialogResult property to anything but DialogResult.None.
Said that your code seems to be not the one usually used to handle a modal dialog.
ShowDialog is blocking your code, you don't exit from this call until the called form is closed or hidden, so you don't need to keep a global variable of FormB around and handle the FormClosed event handler of FormB in FormA.
private void BtnClick(object sender, EventArgs e)
{
using(FormB fb = new FormB())
{
// Here the code returns only when the fb instance is hidden
result = fb.ShowDialog();
if(result == DialogResult.Yes)
{
//open Form C
}
}
}
Now you should remove the call to Form.Close in the FormB code and set directly the DialogResult property of the FormB, do not try to change at this point the DialogResult property of the buttons, this will not work and you need a second click to hide the form, instead set directly the form's DialogResult property.
private const string password = "xxxyyyzzz";
private void BtnPW_Click(object sender, EventArgs e)
{
if(Verify())
this.DialogResult = DialogResult.Yes;
else
{
MessageBox.Show("Error: Incorrect password");
this.DialogResult = DialogResult.No;
}
}
In this way the form is hidden (not closed) and your code exits from the ShowDialog call in the FormA. Inside the using block you can still use the FormB instance to read its properties and take the appropriate paths. When your code exits from the using block the fb instance will be automatically closed and disposed out of existence.
Related
I have a program where I want it to ask a confirmation before close. It's just a simple form with the question and a yes and a no buttons. How can I send the information of which button was clicked back to the main form? All solutions I found were for communication with both forms opened, but when choosing a button in the second for it will close. Any tips or ideas?
The second type of form you described is similar to the MessageBox… You can use its direct implementation as a dialog. Untested Example :
DialogResult dr = MessageBox.Show("Are you Sure?",
"Confirm Exit?",
MessageBoxButtons.YesNo);
if (dr==DialogResult.Yes)
{
// Do work If Yes
}else //if( dr == DialogResult.No)
{
// Do work if No
}
See MSDN for MessageBox
I tend to do it this way.
Code for child form:
private bool _bDoSomething=false;
public bool showForm()
{
this.ShowDialog();
return _bDoSomething;
}
private void btnOK_Click(object sender, EventArgs e)
{
_bDoSomething=true;
this.Hide();
}
And then this sort of code for the parent form:
dlgMyForm dlgMyForm = new dlgMyForm();
if (dlgMyForm.showForm())
{
//do something
}
Declare a boolean value in main form as public
public Boolean check =false;
In the second form's FormClosing event do the following
private void Form2_FormClosing(Object sender, FormClosingEventArgs e)
{
DialogResult answer = MessageBox.Show("[Your text]",MessageBoxButtons.YesNo)
if(answer == DialogResult.Yes)
{
Form1.check=True; //if button yes is clicked
// set the form1 check variable to True and closes form2
}
else
{
Form1.check=False; //if button no is clicked
// set the form1 check variable to False and cancel form
// closing
e.Cancel=True;
}
}
Use the boolean variable check to do further processing in form1
Ok, so a Windows Forms class, WindowSettings, and the form has a "Cancel"-button. When the user clicks the button, the dialog DialogSettingsCancel will pop-up up and ask the user if he is sure he wants to perform the action. The dialog has 2 buttons, a "Yes"-button and a "No"-button. If the user clicks the "Yes"-button, I want both DialogSettingsCancel and WindowSettings to be closed.
My button_Click event handler in DialogSettingsCancel:
private void button1_Click(object sender, EventArgs e)
{
//Code to trigger when the "Yes"-button is pressed.
WindowSettings settings = new WindowSettings();
this.Close();
settings.Close();
}
When I run my application, and go to the settings form, and click the "Cancel"-button, and then click the "Yes"-button, only DialogSettingsCancel closes without closing WindowSettings.
Why won't it work?
I've also tried changing
this.Close();
settings.Close();
to
settings.Close();
this.Close();
But still the same result.
You need the actual instance of the WindowSettings that's open, not a new one.
Currently, you are creating a new instance of WindowSettings and calling Close on that. That doesn't do anything because that new instance never has been shown.
Instead, when showing DialogSettingsCancel set the current instance of WindowSettings as the parent.
Something like this:
In WindowSettings:
private void showDialogSettings_Click(object sender, EventArgs e)
{
var dialogSettingsCancel = new DialogSettingsCancel();
dialogSettingsCancel.OwningWindowSettings = this;
dialogSettingsCancel.Show();
}
In DialogSettingsCancel:
public WindowSettings OwningWindowSettings { get; set; }
private void button1_Click(object sender, EventArgs e)
{
this.Close();
if(OwningWindowSettings != null)
OwningWindowSettings.Close();
}
This approach takes into account, that a DialogSettingsCancel could potentially be opened without a WindowsSettings as parent.
If the two are always connected, you should instead use a constructor parameter:
In WindowSettings:
private void showDialogSettings_Click(object sender, EventArgs e)
{
var dialogSettingsCancel = new DialogSettingsCancel(this);
dialogSettingsCancel.Show();
}
In DialogSettingsCancel:
WindowSettings _owningWindowSettings;
public DialogSettingsCancel(WindowSettings owningWindowSettings)
{
if(owningWindowSettings == null)
throw new ArgumentNullException("owningWindowSettings");
_owningWindowSettings = owningWindowSettings;
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
_owningWindowSettings.Close();
}
You can also close the application:
Application.Exit();
It will end the processes.
new WindowSettings();
You just closed a brand new instance of the form that wasn't visible in the first place.
You need to close the original instance of the form by accepting it as a constructor parameter and storing it in a field.
Why not use the DialogResult method to close the form?
if(DialogSettingsCancel.ShowDialog() == DialogResult.Yes)
{
//this will close the form but will keep application open if your
//application type is "console" in the properties of the project
this.Close();
}
For this to work however you will need to do it inside your "WindowSettings" form while you call the DialogSettingsCancel form. Much the same way you would call the OpenFileDialog, or any other Dialog form.
Your closing your instance of the settings window right after you create it. You need to display the settings window first then wait for a dialog result. If it comes back as canceled then close the window. For Example:
private void button1_Click(object sender, EventArgs e)
{
Settings newSettingsWindow = new Settings();
if (newSettingsWindow.ShowDialog() == DialogResult.Cancel)
{
newSettingsWindow.Close();
}
}
send the WindowSettings as the parameter of the constructor of the DialogSettingsCancel and then on the button1_Click when yes is pressed call the close method of both of them.
public class DialogSettingsCancel
{
WindowSettings parent;
public DialogSettingsCancel(WindowSettings settings)
{
this.parent = settings;
}
private void button1_Click(object sender, EventArgs e)
{
//Code to trigger when the "Yes"-button is pressed.
this.parent.Close();
this.Close();
}
}
for example, if you want to close a windows form when an action is performed there are two methods to do it
1.To close it directly
Form1 f=new Form1();
f.close(); //u can use below comment also
//this.close();
2.We can also hide form without closing it
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
Form2 f2 = new Form2();
int flag = 0;
string u, p;
u = textBox1.Text;
p = textBox2.Text;
if(u=="username" && p=="pasword")
{
flag = 1;
}
else
{
MessageBox.Show("enter correct details");
}
if(flag==1)
{
f2.Show();
this.Hide();
}
}
There are different methods to open or close winform.
Form.Close() is one method in closing a winform.
When 'Form.Close()' execute , all resources created in that form are destroyed.
Resources means control and all its child controls (labels , buttons) , forms etc.
Some other methods to close winform
Form.Hide()
Application.Exit()
Some methods to Open/Start a form
Form.Show()
Form.ShowDialog()
Form.TopMost()
All of them act differently , Explore them !
I am developing a application using windows forms. The project contains 3 forms: one login form which is the main form and two others which are child forms to the login form.
My problem is when want to close the total application by using Application.Exit() in form closing event my messagebox showing the dialog more than once.
1.This code in Login form i.e main form:
private void FrmLogIn_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult loginResult = MessageBox.Show("Do you want to close this application?","Close",MessageBoxButtons.YesNo,MessageBoxIcon.Warning);
if (loginResult == DialogResult.Yes)
{
Application.Exit();
}
}
2.AdminForm closing event which is child form to login form:
private void FrmAdmin_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult loginResult = MessageBox.Show("Do you want to close this application?","Close",MessageBoxButtons.YesNo,MessageBoxIcon.Warning);
if (loginResult == DialogResult.Yes)
{
Application.Exit();
}
}
3.Billoperations form closing event which is child form to login form:
private void FrmBillOperation_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult loginResult = MessageBox.Show("Do you want to close this application?","Close",MessageBoxButtons.YesNo,MessageBoxIcon.Warning);
if (loginResult == DialogResult.Yes)
{
Application.Exit();
}
}
When i click the close button in any form it will show MessageBox message only once. Please help me.
Make all FormClosing methods call a ApplicationShutdown function which handles this in a central place. You don't want to copy this code to every new form you create.
In this method you can check a boolean (watch for thread-safety) called for example IsShuttingDown. If it's already true, leave the method, otherwise you ask the question and start exiting.
The FormClosingEventArgs instance passed to the FormClosing event has a CloseReason property, which will be set to CloseReason.ApplicationExit when the Exit method of the Application class has been invoked: your handlers should check for this condition and if so then take no further action.
private void FrmLogIn_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.ApplicationExit)
return;
...
}
You can try with this code
FormCollection fc = Application.OpenForms;
if (fc!= null && fc.Count > 0)
{
for (int i = 1; i < fc.Count; i++)
{
if (fc!= null && fc.IsDisposed!= true)
{
fc.Dispose();
}
}
}
private void sh_interface_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("This will close down the whole application. Confirm?", "Close Application", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
foreach (Form f in Application.OpenForms)
{
if (!f.IsDisposed)
f.Dispose();
}
}
else
{
e.Cancel = true;
this.Activate();
}
}
This will close all forms including the hidden forms and the main form from Application.Run(new something())...Also this method works when invoked in inherited classes while coded in template class Form Closing event.
I have a login form and a button which check if the user name and the password are true.
but the problem is the code I tried .. I must click on the connect button twice.
but the code should work when I click on the button just once ! Right ?
I think the problem is: the showDialog won't be disappeared if only I click in some button that it's DialogResult set in some value, so in the first click the connexionButton.DialogResult gets the DialogResult.OK value and in the second click the button executes the code.
*you can notice that the event simpleButton1_Click is the event for the connexionButton Button*
this is the event I used :
this.connexionButton.Click += new System.EventHandler(this.simpleButton1_Click);
this is the code I tried :
private void simpleButton1_Click(object sender, EventArgs e)
{
Boolean allowCnx = false;
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
{
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
{
allowCnx = true;
}
}
if (allowCnx)
{
connexionButton.DialogResult = DialogResult.OK;
}
else
XtraMessageBox.Show("Invalide Information", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
and this is the code I used to call this login form :
using (login loginForm = new login())
{
var result = loginForm.ShowDialog();
if (result == DialogResult.OK)
this.Show();
else
this.Close();
}
// Points to a different method than the one you posted
// (simpleButton1_Click_1 instead of simpleButton1_Click)
this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click_1);
// This isn't simpleButton1_Click_1
private void simpleButton1_Click(object sender, EventArgs e)
Not sure if that is your issue, but it looks like your event handler is a different method than the one you posted. Do you have another method called simpleButton1_Click_1 somewhere in your code and you've just gotten slightly confused?
EDIT: In response to your changes/additions
You seem to have some confusion over ShowDialog and DialogResult.
// When you launch the login form, I do not know what you intended to do with your
// calls to Show() and Close() but so long as you don't instend for them to do
// anything to the loginForm, that's fine.
using (login loginForm = new login())
{
if (loginForm.ShowDialog() == DialogResult.OK)
// Do stuff if logged in
else
// Do stuff if failed
}
private void simpleButton1_Click(object sender, EventArgs e)
{
Boolean allowCnx = false;
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
{
allowCnx = true;
}
if (allowCnx)
{
this.DialogResult = DialogResult.OK; // Don't set the DialogResult of a button. Set it for the form.
}
else
{
this.DialogResult = DialogResult.Abort; // Because we didn't succeed
XtraMessageBox.Show("Invalide Information",
"Erreur",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
You are using simpleButton1_Click_1 instead of simpleButton1_Click.
Infact the code should be:
this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click);
EDIT :
yes I just forgot when I copied the event.. I mean
this.connexionButton.Click += new
System.EventHandler(this.simpleButton1_Click);
I think, in this case, you should use a bool instead of a DialogResult, so try:
public bool AllowConnection = false;
private void simpleButton1_Click(object sender, EventArgs e)
{
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
{
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
AllowConnection = true;
}
if (!AllowConnection)
XtraMessageBox.Show("Invalide Information", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
And:
using (login loginForm = new login())
{
loginForm.ShowDialog();
if (loginForm.AllowConnection)
this.Show();
else
this.Close();
}
Change your iterator for your rows from AsEnumerable to Rows.
FROM:
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
TO:
foreach (var row in myClass.ds.Tables["Users"].Rows)
This may sound odd, but if there is any change to that table, anywhere, while you are iterating through your enumerable it will break your iteration. See DataTableExtensions.AsEnumerable This could be perhaps another process accessing this table at the same time, or using a datareader that has not completed filling the table in before the iteration starts.
Also, try to change your code to access the form's dialog result directly, instead of through the button.
FROM:
connexionButton.DialogResult = DialogResult.OK;
TO:
this.DialogResult = DialogResult.OK;
Your code should only set that if your boolean value is set to true, so you will not be closing the form if your checks are correct.
You need to set the Form.DialogResult to DialogResult.OK, not the DialogResult of the Button.
Some Code:
this.DialogResult = DialogResult.OK
Some Additional Thoughts:
It's clearly better to build a standalone method to check for
existence of the user. Don't do this in the ClickEvent. Maybe you need this method again and then you will rewrite this. This will only produce bloated code.
Prevent Users from clicking the Button before Textboxes are filled with values.
I cannot close one of my forms programmatically. Can someone help me?
Here's the code:
private void WriteCheck_Load(object sender, EventArgs e) {
SelectBankAccountDialog sbad = new SelectBankAccountDialog();
DialogResult result = sbad.ShowDialog();
if (result == DialogResult.Cancel) {
this.Close();
} else {
MessageBox.Show(result.ToString());
}
MessageBox.Show(sbad.bankaccountID.ToString());
}
As configurator mentioned (in comments), the form must be shown before it can be closed, so, instead of the Load event, you should be doing this in the Shown event instead.
If you don't want the form visible for the Dialog box, I guess you can wrap the event code in a Visible = false;
In summary, the basic code would be
private void WriteCheck_Shown(object sender, EventArgs e)
{
Visible = false;
SelectBankAccountDialog sbad = new SelectBankAccountDialog();
DialogResult result = sbad.ShowDialog();
if (result == DialogResult.Cancel) {
this.Close();
} else {
MessageBox.Show(result.ToString());
}
MessageBox.Show(sbad.bankaccountID.ToString());
Visible = true;
}
By calling Form.Close(), the form should close, but not until all waiting events have been processed. You also still have a chance to cancel the form closing in the FormClosing event.
First, you'll probably want to return after your call to this.Close(). If it still doesn't close, step through your code and see what is happening. You may have to set and check a "forciblyClose" flag and return from any other processing methods before it'll actually close.
The actual problem is that windows won't let a form close on it's load method. I have to show the dialog on construction, and then if the dialog result is cancel I have to throw an exception and catch the exception on form creation.
This place talks more about it