-1

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`.

Mika Jones
  • 287
  • 1
  • 5
  • 13
  • 2
    *"This seems to be not working"* -- That's not a very informative remark. What do you expect to see when it hits that line, and what do you see instead? Have you put a breakpoint at the top of `BtnClick` and confirmed that it's really getting called, and that you're really following the path you expect through the code? – 15ee8f99-57ff-4f92-890c-b56153 Nov 13 '17 at 18:02
  • My apologies. I skipped some sentences, so I just corrected my question. My code never opens `Form C` even when the correct password is entered in `Form B`. – Mika Jones Nov 13 '17 at 18:04
  • You don't have any code that opens FormC. Add some. – 15ee8f99-57ff-4f92-890c-b56153 Nov 13 '17 at 18:06
  • The code to open `Form C` is there but I omitted it. It never goes inside the `if` statement because `result` gets `cancel` even if I enter the correct password. – Mika Jones Nov 13 '17 at 18:09
  • What is the code inside the FormB instance that closes that form? Do you call this.Close on a form openes modally (ShowDialog())? – Steve Nov 13 '17 at 18:09
  • My apologies again. I forgot to write this.Close() in the question. I edited the code by adding this.Close() after the `if` statement. This still does not work, and `result` value is `cancel` even with the correct password. – Mika Jones Nov 13 '17 at 18:13
  • When you step through `BtnClick` in the debugger, what do you see? Where does it leave the method? What is `result` equal to? – 15ee8f99-57ff-4f92-890c-b56153 Nov 13 '17 at 18:15
  • 1
    youy miss the point of btnPW.DialogResult. This says what result to return if the user clicks that button. It does not say what result to return – pm100 Nov 13 '17 at 18:17
  • 1
    First, it opens `Form B` and I enter the password (incorrect or correct) and hit `Verify` Button, which triggers `BtnPW_Click` method. After reaching this.Close(), it leaves the method, but `result = fb.ShowDialog();` gives `cancel` as the value of `result`. – Mika Jones Nov 13 '17 at 18:18
  • 1
    you are better off setting a field in form b and querying it after the showdialog. Ie have `public bool PasswordOK;` – pm100 Nov 13 '17 at 18:18

1 Answers1

1

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.

Steve
  • 213,761
  • 22
  • 232
  • 286
  • Thank you but this does not close `Form B` even after clicking the BtnPW. Also, adding Close() does not close the form. It closes the form after clicking BtnPW twice... – Mika Jones Nov 13 '17 at 18:30
  • OOps, I had `BtnPW.DialogResult = DialogResult.No/Yes`, and this was causing the problem. Thank you! As soon as I changed it to `this.DialogResult = DialogResult.No/Yes`, it started working <3 – Mika Jones Nov 13 '17 at 19:01
  • As explained above, you shouldn't change the DialogResult property of the Buttons inside the button click event. You have no guarantee that the form engine reads the DialogResult property AFTER your code exits from the event handler. Indeed it reads that property before calling the event handler and, as you experienced, you needed a second click to close that form. Setting directly the form's DialogResult property is the correct way to go in this context. – Steve Nov 13 '17 at 19:33