According to the MSDN document, the close operation on a form shown with ShowDialog() should only cause the form to be hidden. Subsequent calls to ShowDialog() will unhide the form.
This doesn't seem to be case, exactly. I have a form with a tree view on it. The check states are preserved between calls to ShowDialog() but any node expansion the user has done is reset back to its default state. Also, the Load event is being executed every time as well. So it seems to be doing more than just "hiding" the form. Anyone have any idea what's up?
Thanks
I've experienced this issue myself. For some reason, calling Form.Hide or setting visible = false on a modal form will call Form.Close in at least some cases. To work around it I set the opacity to zero. You can also use Form.Show instead.
It is somewhat intuitive if you imagine the behavior of a modal dialogue. It blocks the parent window. So if you hide it then there would be no active window for the user to interact with. FWIW, I think the behavior should have been that the parent becomes active again. That's just not always the case.
Related
I don't understand why this property doesn't have a setter. What would happen if you were able to set this property?
As others have said, it depends on how the form is currently being used, I.e. whether it was Show()ed or ShowDialog()ed. Whilst the form is being shown, it doesn't make sense to allow you to change it's modality1.
When the form isn't being shown, it also doesn't make sense to have this be a settable property since what matters is whether the next use of the form is via Show or ShowDialog.
Whilst it's true that most forms will only ever be shown either modally or non-modally, the option remains open to use a single form in both manners.
1Especially because when a form is being shown modally via ShowDialog, the code calling ShowDialog is blocked until it returns with the result of the dialog. If you were to change a form to be modal after it was already Shown, there's nobody waiting to receive the dialog result when it returns.
The purpose of Form.Modal property, from the documentation:
Gets a value indicating whether this form is displayed modally.
So, it only checks for the modal status of the form. It doesn't make sense for it to have a setter.
In order to open a form modally, you should use the ShowDialog() method, also as explained in the link above. That way when you check for the Modal property, it returns true.
If your question is whether or not you can have a modal form after it's been shown, the answer is no, you can't. To understand why, you need to know how ShowDialog() makes the form modal in the first place. Check this awesome answer by Hans Passant in order to understand how ShowDialog() works at a technical level.
I don't understand why this property doesn't have a setter. What would
happen if you were able to set this property?
It doesn't have a setter because you cant change its Modal style once the Form has been shown. Although subtle, Modal and and Non Modal forms behave differently in regards to owner, and blocking the caller, and other less obvious things. It seemingly just not worth the confusion of adding this i would imagine.
Further more, users must interact with the Modal/Dialog window before they can return to the parent application. This avoids interrupting the workflow on the main window and by design.
So if you want a Modal Form, call ShowDialog() or else call Show()
In summary, I do have a modal dialog in Catel, invoked with:
_uiVisualizerService.ShowDialog(viewModel)
Inside that dialog, I do a long process showing a Wait Service:
_pleasewaitservice.Show();
// HARD WORK here
_pleasewaitservice.Hide();
And Then I invoke another modal dialog.
_uiVisualizerService.ShowDialog(configureViewModel)
However, when I click outside of the application while it is doing the hard work (when the pleasewaitservice is shown), the second modal dialog is displayed behind the main application, so I cannot focus the Window because it is behind and it is modal. I have to close the app from the task killer.
After checking it carefully, I realized that origin is the pleaseWaitService. If I don't show it, the second modal dialog is always displayed correctly.
Does anyone have any hint about how to solve it?
I was googling about how to force to set focus in any Window, but I didn't find anything.
Thanks
Regards
Saul Hidalgo.
You might want to try the BringWindowToTop extension method inside the code-behind of the window:
https://github.com/Catel/Catel/blob/46fcc69575e533eb9e02669ebaa2246894dc98d8/src/Catel.MVVM/Catel.MVVM.Shared/Windows/Extensions/WindowExtensions.cs#L237
I have a form that when I check a box (Duplicate #), a form pops up (CableID_DuplicateView), and I want it to remain ontop until the checkbox is unchecked. However this isn't happening.
I have set the TopMost property to true both dynamically and statically;
this.TopMost = true;
this.TopMost = Checkbox.Checked;
But if I click on anything on the previous form, it gets shoved to the back.
How can I keep it ontop?
Note: I want the other form to still be accessible beneath the top form. And yes, this is an Mdi application, does that make a difference on the TopMost property?
This worked for my similar problem:
try
yourTopForm.TopLevel=true;
yourTopForm.TopMost=true;
yourTopForm.Show(this);
The overloaded Show(this) funcition to show the form is the important part.
It is impossible to make the windows stay on top in MDI system. You can try to activate the windows, so they pop on the top, but this makes only more harm to other actions. I wouldn't recommend trying that. There is just no working way to make some window TopMost in MDI configuration.
Pass your parent form into the Show method of your Top Most form.
When I open from the main screen of the application a child form I also display a user control that should be displayed until the child form is closed or the user closes it. If I set the child form to be usercontrol's parent, the user control is not displayed (so the parent of the user control is the desktop). I used SetWindowPos with HWND_TOPMOST and I get the correct behaviour. now when I close the child form I want the usercontrol to close as well. Do you know what I shoud do to get this?
thanks,
When you Show() the child you can also subscribe to it's Closed or Closing event and use that to properly close the UC.
var f = new ChildForm();
// show userctl
f.Closed += MainForm_ChildClosed_Handler;
void MainForm_ChildClosed_Handler(object s, EventArgs e)
{
// close/hide userctl
}
If you keep a reference towards your usercontrol, you should be able to Close (or even Dispose) it from the Closingevent of his parent.
I don't know what you are doing, a UserControl is meant to be a child control, it should be embedded in a Form. It is technically possible to turn a UC into a top level window (like Form), you'd have to set the TopLevel property to True. That however isn't very productive, the window doesn't have the chrome to make it friendly to use. It is missing the title bar, no easy way for the user to move it around, minimize it, close it. And no easy way to solve focus problems, it can disappear behind another window with no easy way for the user to bring it back to the front. Making it top-most is a hack of sorts to get at least the focusing problem solved, but at rather a deer cost.
Just use the UC as it was intended to be used: put it inside a form. That form should probably be the child form you open. It could also be a third form, say a tool window. Use the Show(owner) overload to keep its Z-order in check and cannot do the disappearing act. That also causes it to automatically close when the owner closes.
I've tried overriding the OnLoad event, but the form is getting drawn before this method finishes. I am calling the base.OnLoad method. But, the form is partially getting drawn (artifacts are seen) during the event. I notice this because I'm hitting the database and it is taking some time. In the event, I'm getting some data and binding it to the form's controls. Please don't tell me to use a separate thread. For simplicity, I would rather just show a busy cursor while the data is being loaded.
UPDATE:
Ok, I think you guys/gals have convinced me. I'll use a separate thread. I wasn't aware of the BackgroundWorker and it was very easy to implement. Now my form is loading quickly. And then, all of a sudden my combo boxes are populated. But, I'd like prevent the user from clicking on the combos before they're populated. What is the best way/standard way of doing this using Winforms? Is there a way to turn off input events in the form until the background worker is finished?
I would recommend that you cover the form with a Loading label before you start loading.
You should be able to solve the problem by placing your loading in the constructor code before the call to IntializeComponent(). At this point, the controls on the form have not yet been created (because this is what InitializeComponent does).
However, the form is also not yet visible in this phase. If you want to show a blank form, then I think a possible solution (I haven't tried that, but I think it should work) would be to call this.Show() (to display the form) and Application.DoEvents() to let WinForms process events and display the form.
You could try doing your expensive operations in the form's constructor, so that when it's time to show the form, it already has the data it needs to render. Also look into SuspendLayout/ResumeLayout methods.
But none of these solutions will be as graceful as using a different thread to perform expensive operations.
I am not sure if this will help or not, but the Move event is called before Load.
The Shown event is good for this. Your form will be completely displayed, then the Shown event is fired. This will give the user a clean screen without partially drawn fields while you load your data.
In your Shown event handler, turn on the hourglass, do your work and then turn off the hourglass.
The ComboBox has a BeginUpdate() and EndUpdate() that can be called when adding large amounts of data or slow data to the control. SuspendLayout() and 'ResumeLayout()` on the form may also help with your redraw issues.
You can also disable the control, if all you want is to prevent the user from clicking it. If you disable the form itself, all contained controls will also be disabled.
If you're using background threads, you'll have to make sure you call these from the main UI thread before starting the thread, and again from the main UI thread when the background worker is complete.