lzdyzydy
lzdyzydy

Reputation: 69

Replacing ShowDialog() with Show()

I have a form that is being shown using ShowDialog(), thus it is a modal window.

private void OpenForm(object sender, ItemClickEventArgs e)
{
    MyForm testForm = new MyForm();
    ...
    testForm.Enabled = true;
    testForm.ShowDialog(this);
    var dialogOk = testForm.DialogOK;
    if(dialogOk)
    {
       //do some stuff 1
    }
}

There is an "OK" button on the form. When OK is clicked, DialogOk is set to true. Inside MyForm class:

private void OkClick(object sender, EventArgs e)
{
   // do some stuff 2
   ... 
   DialogOK = true;
   Hide();
}

I need to convert this to a non-modal window. The solution seems to be to use Show() instead of ShowDialog(), but when I use Show(), the code does not stop and wait for the OK button to be clicked, so "do some stuff 1" is never called.

Using Show(), how can I keep the behavior to have "do some stuff 1" run after the OK button is clicked?

Update: Here is what I am trying now:

public partial class MyForm: XtraForm
{
   public bool DialogOk;

   private void OkClick(object sender, EventArgs e)
   {
      // do some stuff 2
      ... 
      DialogOk = true;
      Close();
   }
}

Method 1:

public partial class MyMainForm : XtraForm
{
   private MyForm testForm;

   private void OpenForm(object sender, ItemClickEventArgs e)
    {
        if(testForm == null)
        {
            testForm = new MyForm();
        }
        ...
        testForm.Enabled = true;
        testForm.FormClosed += (s, a) => {
            var dialogOk = testForm.DialogOk;
            if (dialogOk)
            {
                // do some stuff 1
            }
        };
        testForm.Show(this);
    }
}

Method 2:

public partial class MyMainForm : XtraForm
{
       private MyForm testForm;

       private void OpenForm(object sender, ItemClickEventArgs e)
        {
            if(testForm == null)
            {
                testForm = new MyForm();
            }
            ...
            testForm.FormClosed += testForm_Closed;
            testForm.Show(this);
        }

        private void testForm_Closed(object sender, EventArgs args)
        {
            var testForm = (Form)sender;
            testForm.Closed -= testForm_Closed;

            if (testForm.DialogResult == DialogResult.OK)
            {
               // do some stuff 1
            }
        }
 }

Upvotes: 2

Views: 1819

Answers (4)

pm101
pm101

Reputation: 1424

This works for me, so not sure why it isn't for you (scratching head)... This form has two buttons, one which opens the same form again and another button that closes the form. The 'parent' form adds an event to the Closed event.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form1 test = new Form1();

        test.FormClosed += Test_FormClosed;

        test.Show();
    }

    private void Test_FormClosed(object sender, FormClosedEventArgs e)
    {
        MessageBox.Show("closed -- do something else here!");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Close();
    }
}

Upvotes: 0

Nkosi
Nkosi

Reputation: 247008

You can use an async event handler tied to an TaskCompletionSource which listens and awaits the close of the form

private asyc void OpenForm(object sender, ItemClickEventArgs e) {
    var source = new TaskCompletionSource<DialogResult>();

    EventHandler handler = null;
    handler = (s, args) => { 
        var  form = (MyForm)s;
        form.FormClosed -= handler;
        source.SetResult(form.DialogResult);
    }

    var testForm = new MyForm();
    testForm.FormClosed += handler; //subscribe
    //...
    testForm.Enabled = true;
    testForm.Show();

    var dialogOk = await source.Task;
    if(dialogOk == DialogResult.Ok) {
       //do some stuff 1
    }
}

With that you can keep the logic in the OpenForm and allow the code to wait without blocking.

In the form when the button is clicked then all you need to do is set the dialog result and close the form.

public partial class MyForm: XtraForm {

    //...

    private void OkClick(object sender, EventArgs e) {
        // do some stuff 2
        // ... 

        DialogResult = DialogResult.Ok;
        Cose();
    }
}

Upvotes: 0

Markus
Markus

Reputation: 22436

The easiest way is to move the code from OpenForm to the event handler OkClick. However, if this is not a good spot to put the code because you might want to use the same form for different tasks, you could add a handler for the FormClosed event, that is called after the form is closed and runs the code, e.g.:

private void OpenForm(object sender, ItemClickEventArgs e)
{
    MyForm testForm = new MyForm();
    ...
    testForm.Enabled = true;
    testForm.FormClosed += (s, a) => {
      var dialogOk = testForm.DialogOK;
      if(dialogOk)
      {
         //do some stuff 1
      }
    };
    testForm.Show(this);
}

Upvotes: 1

opewix
opewix

Reputation: 5083

You can handle Form.Closed event:

MyForm testForm = new MyForm();
testForm.Closed += testForm_Closed;
testForm.Show();

private void testForm_Closed(object sender, EventArgs args)
{
    var testForm = (Form)sender;
    testForm.Closed -= testForm_Closed;

    if (testForm.DialogResult == OK)
        // do some stuff 1
}

Upvotes: 3

Related Questions