Winforms child window disappears behind owner - winforms

I have a winforms MDI app where a window that is a "child" of the MDI form pops up a dialog, like this:
AddPartsForm partsForm = new AddPartsForm( );
partsForm.StartPosition = FormStartPosition.CenterParent;
DialogResult result = partsForm.ShowDialog( this );
As you can see, I have attempted both to center the dialog within its parent, and to establish who the parent is. This generally works. The dialog itself is a form with a dropdown list from which to select something that fills a grid on the same form. Occasionally, the loading of the grid takes up to ten seconds.
During the loading, I am careful not to move my mouse or click on anything. Yet, every so often (but not always) when the grid loads, the dialog "disappears" behind the form that called it. I can find it in the system tray, but I want this not to happen. There must be a parent/child or owner/child convention that most everyone uses and I have missed, because I do not see this kind of behavior in most software that I use.

Related

Two contents that overlap each other

Let me try to explain scenario: I have a main view that looks like this (simplified):
<Grid>
<ContentControl Content="{Binding RegularScreen}" /> <!--used for "regular" application views -->
<ContentControl Content="{Binding DialogScreen}" /> <!-- used for dialog view -->
</Grid>
Regular screen is created first. While working on regular screen, a user triggers an action that requires a dialog screen to be shown to user. This dialog screen must cover completely the application, must not allow user to perform any other action but on this dialog. Dialog screen exists to:
allow user to choose from given options
when user selects an option, dialog screen closes, and this information is passed to regular screen.
To return to above code, when dialog screen is shown, DialogScreen is set to an instance of dialog screen. This is where the problem comes:
now we have both RegularScreen and DialogScreen contents shown (although the second one is visually overlapping the first one). Since in RegularScreen I have some InputBindings that monitor the keyboard, when I press some key while DialogScreen is shown, RegularScreen captures the key?!? This should never happen, and the only screen that should be handling the keys is DialogScreen (since it is on top of RegularScreen).
Any ideas why is this happening and any advice about what to change in design?
The reason why I have decided to have DialogScreen overlapping RegularScreen, is because RegualarScreen is quite complex screen, contains many tabs, and is very time/resource consuming to destroy it / recreate it every time a dialog screen is shown. This way I keep it "alive", and after I close the dialog screen, it shows immediately.
What you are describing is the natural effect of opening a dialog Window using window.ShowDialog. From the linked page:
ShowDialog shows the window, disables all other windows in the application, and returns only when the window is closed. This type of window is known as a modal window.
So, as you can see, this automatically disables all other windows in the application. Perhaps you should try that instead?

WPF Modal dialog goes in background

I have problem with an application where modal WPF dialog occasionally goes behind the main application window. This hapens when I click button on the dialog which does some processing and updates controls (through binding) in the main application window. When it goes in background - clicking anywhere in the application brings it back into foreground.
var dialog = LoadDialogWindowThroughMEF();
dialog.Owner = Application.Current != null ? Application.Current.MainWindow : null;
dialog.ShowInTaskbar = false;
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
return dialog.ShowDialog();
The above code shows how I open modal window. This happens very rarely.
Does anybody know what could be the problem?
I'm not sure I have an answer for you, but I can share some of my thoughts:
Every time I've encountered this type of problem, it happened because the Owner wasn't set properly. So, I'd try to not set the Owner and see if that makes the problem reproducible. You need to be absolutely sure that Owner is set to the correct parent window at all times1. You might also want to check that it is the actual MainWindow of your application that are supposed to be the parent. I think that most of the time it is beneficial to be explicit2 in your code. In this case that means that it is better to assign the known parent (maybe you have a reference to the parent somewhere that you could use), rather than relying on the Application.Current to provide you with that reference. Doing so will put you in control of the assignment to Owner. It could even make it possible to get rid of the ?: operator since you would have the means to control the reference even during unit testing.
I also want you to make sure that the code that is actually updating the parent window doesn't in any way force focus to a specific control on the parent window, or anything like that. (As long as the correct parent is set as Owner, I don't see this as a likely problem.)
I hope this helps you, but I understand if it doesn't. The fact that your dialog reappears when you click the parent window disproves some (or all!) of my points...
1 Except when running your unit tests, but that's a completely different matter.
2 As in the first meaning of the word according to wiktionary.org/wiki/explicit, and as opposed to implicit.

Is it safe to show multiple dialogs in WPF?

Surprisingly one can show more than one dialog at a time by putting the ShowDialog() call on the Dispatcher:
uiDispatcher.BeginInvoke(new Func<bool?>(myWindow.ShowDialog));
How come this works and still the UI remains running responding to user interaction once the dialog is shown (I would have thought not since ShowDialog() blocks the thread it is on which has to be the UI thread), one can even go on showing new dialogs:
Window myWindow;
for(int i = 0; i < 5; i ++)
{
myWindow = new Window();
uiDispatcher.BeginInvoke(new Func<bool?>(myWindow.ShowDialog));
}
And the UI is still responsive.
Is there something I should beware of relying on this behaviour? (I want to show one dialog on top of another when some background thread wants to - this works - the only unwanted behaviour seems to be when switching apps sometimes WPF does not know which dialog should be on top - but still allows you to bring one of the dialogs to the front by clicking on it which is unusual for a dialog as clicking outside a dialog is usually not allowed).
UPDATE: One issue I have come across is if you hide one of your dialogs the user can interact with all other Windows again! (not just the other dialogs). See: WPF Dialog not modal?
Showing a dialog does not block the UI thread -- otherwise you won't be able to interact with the dialog.
It merely marks the fact that there is a modal dialog outstanding, and that it should disable inputs to all other non-dialog windows.
If you shuff a ShowDialog call into the dispatcher, the dispatcher will allow an additional dialog to be created because you are not doing something which is prohibited when a modal dialog is outstanding -- which is to input into other non-dialog windows.
Your new dialog is fully functional, because it is a dialog, and you are not trying to input into non-dialog windows.
Switching applications should bring any modal dialog out to the front, but since you have more than one modal dialogs, the system will get confused as to which one should be top-most. I'd suggest you trap the activation event and just manually bring the necessary dialog top-most.

In forms application, is there any Alternative to MsgBox?

I like how MsgBox stops all further processing until it's clicked but I don't like how it pops that little msgbox in the middle of the screen. Is there a way to do something like a msgbox but keep it on my Form (which is always in view) so I can go ahead and click a button on the form instead of having to bring the little msgbox window on top of windows that may be covering it.
I use the msgbox to inform me that a certain situation has happened, which I manually fix and when I'm done I click the MsgBox to continue processing. It'd be nice to have this button right on the form.
which I then have bring to the front if there is a window covering it
That shouldn't happen, but can happen if you display the message box from a thread in your program. The window has the desktop as the parent and has no Z-order relationship with the windows in your user interface. And yes, can easily disappear behind the window of another app, including your own.
There's a MessageBoxOptions option that isn't exposed in Winforms, MB_TOPMOST, which ensures the window is top-most. You'd use it like this:
MessageBox.Show("text", "caption", MessageBoxButtons.OK,
MessageBoxIcon.Information, MessageBoxDefaultButton.Button1,
(MessageBoxOptions)0x40000); // use MB_TOPMOST
But by far the best thing to do is to display the message box on your UI thread. Use Control.Invoke() to do so. That way the other windows of your app are disabled, no way for the user to not notice the box.
Still one problem with this, the user won't expect the box to show up since it is shown asynchronously from anything she does. Which means the box can easily get dismissed by accident when the user just happened to press the Enter or Space key. Or clicked at just the wrong spot. Nothing much you can do about that.
Centering the box in your main window is technically possible, but fugly to do. Check this answer.
Do you mean that the form shall exchange its contents with a message plus an OK button?
This would be similar to the way a text mode interface typically works.
You can make it happen by adding a disabled panel or UserControl with message and button topmost on the form and enable it when you wish to alert the user. However, I am puzzled how to implement the blocking behavior similar to MessageBox.Show() and Dialog.Show().

Clicking MDI children form doesn't bring it to front

This is a winform question in .net.
In a MDI form, if I open several children forms, for some forms, if they are not activated (if you overlap them with the activate one, they are not up to front. Only the activate form is up to front.), clicking them don't bring them to front. This is even true if I click controls on them, such as a textbox. The textbox gets focus and you can intput things, but that form is still not activated.
Interestingly enough, this is not the case for all the children forms I created. Some forms behave correctly but others don't. Did I do something wrong?
I think the correct behavior is that, everytime I click a form, bring it up to front.
Thank you for any suggestion.
childForm.MdiParent = Me
childForm.WindowState = FormWindowState.Maximized
childForm.Show()
childForm.Focus()
try this
childForm.ShowDialog(Me)

Resources