Closing messagebox from modal dialog closes the dialog - wpf

I have a custom modal dialog from which I want to invoke a Messagebox on error.
However on closing the messagebox, the dialog also closes.
Is there a way to keep the dialog open and just close the messagebox?

This seems to be the same issue as the one mentioned here. I found a way to fix it and through it, probably proof that it is indeed a bug. My solution, as mentioned here:
A workaround on this is to add a handler for the FormClosing event of your form, so you can cancel it there.
It seems that the bug is somewhat detectable by checking FormClosingEventArgs.CloseReason. This is normally "UserClosing" on normal close (even programmatically with calling this.Close()), but with this bug it's set to "None", a value I would assume is some kind of default that should normally never be used.
private void form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.None)
{
e.Cancel = true;
return;
}
// any other OnClose code you may wish to execute.
}
[EDIT]
Sorry, the issue in the linked question was OP using form.DialogResult as temp variable for the result of a message box, and that caused the main form to close, so that is, in fact, not related. Use a temp variable for stuff like that, folks.
The most likely real cause of this is that the form's AcceptButton is set, and the actual accept button's code does validation. Even if the validation raises an error, AcceptButton will cause the form's DialogResult to be set to OK, which closes the form. To prevent this, either don't set the AcceptButton property and just set the DialogResult manually, or, on error, specifically clear the DialogResult by setting it to DialogResult.None.

Related

Form closing immediately

Dim details As New frmDetails(ID, JobID, True)
details.ShowDialog()
The form flashes open and immediately closes. If I use Show() rather than ShowDialog() it stays open and look fine. Here are some things I've checked:
Breaking in FormClosing shows only
System.Windows.Forms.Form.OnFormClosing
System.Windows.Forms.Form.CheckCloseDialog
System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FContinueMessageLoop
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
System.Windows.Forms.Application.ThreadContext.RunMessageLoop
System.Windows.Forms.Application.RunDialog
System.Windows.Forms.Form.ShowDialog
between the ShowDialog and the FormClosing.
CloseReason is "None"
Load runs to the end, as does VisibleChanged (though Activated never gets called).
There's no sign of any Exceptions being thrown.
Intellitrace doesn't show anything going on.
After the form closes, the DialogResult is "Cancel" (There's no reference to DialogResult in the form or its Designer)
I'm not doing any explicit threading
I'd appreciate any suggestions either as to what's going on or how to go about finding out.
Thanks.
In my case I was setting the DialogResult property on the load event to Cancel, and that was causing the dialog to close immediately after Load. I've set it to the default None and now I only set it to other value on the Click event of a button when I really need to close it.
Well, this will probably do nobody any good, but here's how I solved the problem:
There was a line in the Load method that read
Me.Text = ""
I have no idea what it was doing there (this isn't my code, thank goodness), especially since the value gets set again later on, but taking that line out stopped the form from mysteriously closing. Go figure.
I had a similar problem. In my case it was due to not specifying the parent window on the ShowDialog(). The dialog associated with the window that was topmost, which happened to be a combobox drop-down that was going away.
In my case, I changed the ShowDialog() call to use my application's main window as the parent, and problem solved.
Been debugging for couple of hours with the same problem. In my case the likely reason was that the parent form has setting ShowInTaskbar = false in Load event, while my form had this set to true in the designer. For some reason this caused the dialog result to be set to Cancel during initialization.

Why is Dialogresult nil?

This never happened to me before.
I do have System.Windows.Forms namespace under uses clause and I am able to use DialogResult's properties. Look at the code below. It's where the problem is in my program.
if (thewinform.ShowDialog=DialogResult.OK) then
I did debug it and dialog winform opens. Once I click the OK button and returns to check on the DialogResult, it skips the if block of code. At which point, I noticed that DialogResult is actually NIL
I never encountered anything like this before.
Any ideas? Thanks,
I found the answer to my question.
When you want to use a winform purely as a dialog box, then you CANNOT have FormClosing event.
For my thewinform, I accidently created its FormClosing event and forgot about it.
method thewinform.thewinform_FormClosing(sender: System.Object; e: System.Windows.Forms.FormClosingEventArgs);
begin
e.Cancel := true;
hide;
end;
Once I removed this winform event, ShowDialog and DialogResult is behaving as expected.
This is very similar to another stackoverflow question Why does ShowDialog always return DialogResult.Cancel?

give focus to textbox when control is shown

There is a custom UserControl which contains a TextBox. How do I give focus to the textbox when UserControl is shown? I've tried calling TextBox.Focus on UserControl.IsVisibleChanged and TextBox.IsVisibleChanged event, but that didn't help. What else can I try?
It seems that something causes TextBox to loose focus. The approach that I've mentioned normally works. How can I find out what causes the TextBox to loose focus? I've tried listening to TextBox.LostFocus event, but it's parameters don't contain much valuable information and I also don't see previous methods in the stack trace.
The code:
void TextBox1_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.TextBox1.IsVisible)
this.TextBox1.Focus();
}
As I've said before, it works if I use same code on a similar scenario in a test project, but it doesn't work in my application (the application is big and I am basically fixing bugs in it, and this one is amongst them). So I think that the problem isn't that focus is set improperly (as I've thought when I was opening this question), I think that the problem is that something else resets the focus. I am trying to find what it is here: Find out why textbox has lost focus .
I'm not exactly sure why it doesnt come back on visibility changed... however when I did TextBox1.Focus() in IsEnabledChanged it worked like a charm.
Use the UC as the bridge, when you let the UC shown, then call some function to focus the TextBox.

What's the best way to prevent losing TextBox focus when there is a validation error?

I've messed around with PreviewLostKeyboardFocus which almost gets you there. I've seen a couple of implementations using LostFocus, but that just forces focus back on the TextBox after it's lost focus and you can easily see this shifting on the screen. Basically, I'm just looking for the same type of behavior you could get with using OnValidating in WinForms.
In my opinion, the best way is generally not to do it. It is almost always better to just disable the other controls or prevent saving until the value is valid.
But if your design really needs this ability, here is what you should do:
Intercept the Preview version of keyboard and mouse events at your window level, or whatever scope you want to prevent focus changes within (eg maybe not your menu bar).
When the Tab KeyDown or Return KeyDown is detected in the text box, or when a MouseDown is detected outside the text box while it has the focus, call UpdateSource() on the binding expression, then if the validation has failed set Handled=true to prevent the KeyDown or MouseDown event from being processed further.
Also continue handling PreviewLostKeyboardFocus to catch any causes of focus change that aren't from the keyboard or mouse, or that your other code didn't recognize.
To add onto Ray's answer:
UpdateSource is called like so:
BindingExpression be = userTextbox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
Also, as an alternative you can set the text box binding to:
UpdateSourceTrigger = "PropertyChanged";
The latter will cause a continuous check, whereas the former will check when needed (performant).
If you attempt to focus an element inside its own LostFocus handler you will face a StackOverflowException, I'm not sure about the root cause (I suspect the focus kind of bounces around) but there is an easy workaround: dispatch it.
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var element = (sender as TextBox);
if (!theTextBoxWasValidated())
{
// doing this would cause a StackOverflowException
// element.Focus();
var restoreFocus = (System.Threading.ThreadStart)delegate { element.Focus(); };
Dispatcher.BeginInvoke(restoreFocus);
}
}
Through Dispatcher.BeginInvoke you make sure that restoring the focus doesn't get in the way of the in-progress loss of focus (and avoid the nasty exception you'd face otherwise)

Setting DialogResult only after ShowDialog() in WPF

I have a window that I sometimes open using Show() and sometimes using ShowDialog(). In the second case, the returned dialog result is important for me. But if I set the DialogResult after calling Show() I get an InvalidOperationException. Is there a way to find out which method was used to open the window and set or not the DialogResult accordingly? Or is there another way?
Of course I know I can catch and ignore the exception, but I don't like this solution.
Use System.Windows.Interop.ComponentDispatcher.IsThreadModal inside the window to determine if it runs on a modal thread or not.
If you look at set_DialogResult in Reflector, it checks _showingAsDialog to determine whether the dialog is modal. Unfortunately this is a private field.
Do you always construct a new instance of the window before calling Show()/ShowDialog(). If so, you could pass an argument to the constructor indicating how it is to be shown.
You can use the Form.Modal property to check the kind of usage.
In the case of using Form.Show() you have to use another way to let the caller know of any results of the Form.
Is there a reason to use both ways of showing the form?
How about just setting this.DialogResult = DialogResult.blah in the form closing event?

Resources