Execute code after dialog closed and it's not visible - c#

I want to execute some code inside 'Form1' but after the dialog is closed and it's not visible. I know that I can do this outside the dialog after calling ShowDialog() but I don't like it.
I tried in 'FormClosed' but it seems that the dialog it's still visible when this event is fired. Also if I call 'Hide()' the main dialog it's minimized - something interesting happens

I would create a static method on the dialog, and in this method show the dialog, and execute whatever needs executing after it closes, e.g.
public static void ShowAndDoStuff()
{
MyDialog dialog = new MyDialog();
dialog.ShowDialog();
dialog.DoStuff();
}

You can try Closing Event, also the hide method is a good idea.
I suggest a mix solution
just use a boolean variable (ie: sysclose ) with false default value,
in the closing event if sysclose is false then cancel the close and hide the form then do your job set the sysclose to true and call this.close

Related

what is the difference between show and showdialog in term of form closing in c#.net

I am working on winform application where I need to display a popup. I am currently doing it with ShowDialog() method. but due to change in requirement, I want to show it as non-dialog. So I have used show() method instead of showDialog().
my popup window is using windows webBrowse control as one of its child control.
my problem is when I use showDialog() method, everthing works fine.
but when I use show() method, and close the popup (once user is done with his work), show method() somehow calling dispose method of webBrowse control and this is preventing me to relaunch same popup again and giving me "Cannot access a disposed object" error.
Is this expected behavior in show() method or webBrowse control. if yes, then how Can I resolve it.
Note: PopUp dialog box is injected in presenter using DI so cannot inject popup after every dispose.
Thanks in advance.
By using showdialog() you can not go back to your parent form, by simply using show() you can go back, that's all
With Show(), your code proceeds to the line after the Show statement. With ShowDialog(), it does not.
You could try using Hide()instead of Close().
Put this in the constructor of your dialog window (this is a WPF example)
public Window()
{
this.Closing += Window_Closing;
}
And then cancel the close event and hide the window instead like this
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
}
After that you should be able to reopen a closed window, beacuse it's not disposed but hidden. Problem with this is, that you have to manually clean the content of the window before reopening it, because otherwiese it contains the conten of the last use.

Exit application by clicking button on mainform when already pop up form is running

Form2 is user confirmation window,i want to close the application by stop button on mainform,but currently form2 is active and there is no dependency between form2 and mainform.How to close application ?
You must be opening Form2 using ShowDialog() method. Instead of that use Show() method and on MainForm button's click event call Application.Exit() method
You can use...
// for WinForms application
if (System.Windows.Forms.Application.MessageLoop)
{
System.Windows.Forms.Application.Exit();
}
// for Console application
System.Environment.Exit(1);
So your problem is the parent window will not have focus/input until the modal window (the confirmation dialog) has finished.
So, to avoid this, just make the confirmation dialog using a custom window (instead of a common dialog / msgbox) and show it. This way if the user wants to click your main form they can (the confirmation will be on background, covered by the main window because of this).
it looks like you're showing the dialog as ShowDialog() or showing a built in MessageBox which is also a ShowDialog that needs to be closed in order for focus to return back to main window. So what you should do is create a custom Dialog and use dialog.Show() method. This will allow you to interact with your main window while the dialog is open and you can click on a button to close your application regardless of the dialog being open or not. Following code should do the closing work for you
Application.Current.ShutDown();

MessageBox shown before form closes

Why is the messagebox shown before the form closes?
SomeForm myForm = new SomeForm();
myForm.Show();
MessageBox.Show("Some text");
Do I need to start a new thread, and wait for it to finish? I've never come across this problem before.
You need to use Form.ShowDialog() instead. Form.Show shows a modeless window, whereas Form.ShowDialog shows a modal form, i.e., that the user has to close before continuing.
Your example never actually closes myForm...only shows it. I would expect the code above to show myForm and then immediately show the MessageBox.
If you want myForm to close before showing the MessageBox, you'll need to call myForm.Close() at some point.
The reason for this is that myForm.Show(); starts the opening of a new window, however it is not a blocking call. It's not a dialog, it's a separate window, which runs on it's own.
If you want SomeForm to show as a Dialog (blocking window, waits for close to continue execution), then use ShowDialog. If you want to wait till the window is opened before you show the MessageBox, then add the MessageBox to the OnLoaded on the SomeForm claa.
If it's important that the user not be able to interact with the main form while this other form is being shown then you can use myForm.ShowDialog instead of Show. ShowDialog is a blocking function, so it won't return until the other form is closed. Show, on the other hand, just shows the other form and then immediately returns without waiting for the form to be closed.
If it's intentional that the other form is not being shown modally, and you don't (or can't) make that change, then you can use events to show a message box when the other form is closed.
SomeForm myForm = new SomeForm();
myForm.FormClosed += (form, args) =>
{
MessageBox.Show("Some text");
};
myForm.Show();
This will add an event handler, which fires when the other form is closed, and executes the desired code at the appropriate time.

Why can we get the pressed button in OpenFileDialog without a listener?

In C# we can do something like:
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
pbxPhoto.Image = new Bitmap(dlg.OpenFile());
}
But why can we find out what button was pressed without a listener? Does the program flow stop right before the "if" clause till the open file dialog is closed?
The ShowDialog() method of the OpenFileDialog class internally handles the button click events, and then returns a DialogResult return type indicating which of the buttons was pressed. (So yes, the method is called synchronously, so flow through your calling method does stop until the dialog returns.).
You can mimic this behaviour if you write your own modal dialog class (or user control), in which you handle the button click events internally in the dialog class and then provide an enumeration as a result to encapsulate the internal workings of the dialog.
As an alternative you could add your own handler to the FileOk event, but this would probably make more sense using non modal Show() as per Justin's answer.
I think the answer is yes. The ShoweDialog call will block until the modal dialog is closed. If you want different (i.e. non-modal) behaviour, you need to call Show() instead.
ShowDialog is a modal form which means that it must be dismissed before the application returns to its normal states. When ShowDialog method is called, it returns an enum containing the states after one of the buttons on the Dialog Box is pressed. For example, if the user presses OK, then the DialogResult is set to OK and is returned to the caller. The caller then determines what to do from the returned result (Enum).

How to create a non-modal form but blocking?

Should sound weird, but this is just for my hobby. I would want a (custom) messagebox to pop up with a YesNo buttons which should ideally block the code. But I should be able to click on the parent form so that I can dismiss the message box without having to specifically click on the messagebox buttons (equivalent to clicking No on the message box)..
something like this:
void Foo()
{
CustomMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block the code here, but user should be able to click on form, so that its equivalent to have clicked No;
//if clicked No, return;
//delete.
}
So the solution I thought was make the custom message box non modal - so that user can click on form, but I'm not able to block code.. How can i do that?
It would look like this:
void Foo()
{
NonModalMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block thread till user clicks on form or messagebox buttons.
//unblock when user clicks.
//if No, return;
//delete.
}
Edit: I know this is not a standard practice and I know non modal forms do not block, while modal forms do. So please do not recommend to be content with either modal form's or non-modal form's behavior. My question would be is there any way to simulate the behaviour of ContextMenu with windows forms.
You can solve this quite easily. Create and use a modal dialog but override the WndProc of the dialog and process the WM_MOUSEDOWN event. Check the position of the mouse down and if it is over the parent window but not over the dialog itself then simply dismiss the dialog.
Essentially you can't do this in a 'blocking' call easily. What you could do easily enough is to either pass the information required to perform the delete, or a delegate to perform the operation, to the form. When they click Ok you simply perform the operation. If they activate the parent form, then just close the child.
You want the user to be able to click the background window to cancel the dialog box? Add a handler to the background window so that when the user clicks on it you check to see if the non-modal window is displayed, if so close it.
Sounds easy, but you will need to be careful to handle every possible click on the background window and child windows. That sounds like a can of worms I wouldn't want to go down.
Perhaps instead you could detect if the non-modal dialog box loses focus and automatically close it. I can see this behavior making sense for a simple "confirm delete" dialog box, but as a user my first reaction is going to be to spam the ESC key to close the dialog box.
Another way of handling this is by manually enabling the parent form when calling ShowDialog, from here
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool enable);
internal static DialogResult ShowDialogSpecial(this Form formToBeShown, Form parent)
{
parent.BeginInvoke(new Action(() => EnableWindow(parent.Handle, true)));
formToBeShown.ShowDialog(parent);
return formToBeShown.DialogResult;
}
Just call the extension method from any parent form like this:
var f = new Form();
f.ShowDialogSpecial(this);
//blocks but parent window will be active.
Of course you need to handle the clicks on parent form to close child form.
You could do something like:
public void ShowMe() {
Show();
while (!_receivedDeactivateEvent)
Application.DoEvents();
}
I'm not sure I'd recommend it, though -- I'm not sure how stable it would be, nor am I sure whether it would behave the way you want if you click the Delete button on the parent form while the 'dialog' is up (would it close the first dialog first, or leave it up? might be the latter, which could get messy).
An easier way: set form's "TopMost" property to be True. Then it will act like blocking

Categories

Resources