I hope I can explain this clearly enough. I have my main form (A) and it opens 1 child form (B) using form.Show() and a second child form (C) using form.Show(). Now I want child form B to open a form (D) using form.ShowDialog(). When I do this, it blocks form A and form C as well. Is there a way to open a modal dialog and only have it block the form that opened it?
C# – Is it possible to use ShowDialog without blocking all forms
cshowdialogwinforms
Related Topic
- C# – Windows forms: ShowDialog – dialog doesn’t show up
- .net – Windows Forms and ShowDialog problem
- C# – Is it possible to use ShowDialog from MdiChildForm without blocking all others MdiChildForms and MdiParent
- C# – All possible array initialization syntaxes
- C# – Try-catch speeding up the code
- C# – Why does closing a nested child dialog also close the parent dialog
Best Answer
Using multiple GUI threads is tricky business, and I would advise against it, if this is your only motivation for doing so.
A much more suitable approach is to use
Show()
instead ofShowDialog()
, and disable the owner form until the popup form returns. There are just four considerations:When
ShowDialog(owner)
is used, the popup form stays on top of its owner. The same is true when you useShow(owner)
. Alternatively, you can set theOwner
property explicitly, with the same effect.If you set the owner form's
Enabled
property tofalse
, the form shows a disabled state (child controls are "grayed out"), whereas whenShowDialog
is used, the owner form still gets disabled, but doesn't show a disabled state.When you call
ShowDialog
, the owner form gets disabled in Win32 codeāitsWS_DISABLED
style bit gets set. This causes it to lose the ability to gain the focus and to "ding" when clicked, but doesn't make it draw itself gray.When you set a form's
Enabled
property tofalse
, an additional flag is set (in the framework, not the underlying Win32 subsystem) that certain controls check when they draw themselves. This flag is what tells controls to draw themselves in a disabled state.So to emulate what would happen with
ShowDialog
, we should set the nativeWS_DISABLED
style bit directly, instead of setting the form'sEnabled
property tofalse
. This is accomplished with a tiny bit of interop:The
ShowDialog()
call doesn't return until the dialog is dismissed. This is handy, because you can suspend the logic in your owner form until the dialog has done its business. TheShow()
call, necessarily, does not behave this way. Therefore, if you're going to useShow()
instead ofShowDialog()
, you'll need to break your logic into two parts. The code that should run after the dialog is dismissed (which would include re-enabling the owner form), should be run by aClosed
event handler.When a form is shown as a dialog, setting its
DialogResult
property automatically closes it. This property gets set whenever a button with aDialogResult
property other thanNone
is clicked. A form shown withShow
will not automatically close like this, so we must explicitly close it when one of its dismissal buttons is clicked. Note, however, that theDialogResult
property still gets set appropriately by the button.Implementing these four things, your code becomes something like: