A WPF window dialog is shown using the ShowDialog method in the Window class like when a button is pressed on the main window, like this.
private void button1_Click(object sender, RoutedEventArgs e)
{
try
{
var window = new Window1();
window.ShowDialog();
}
catch (ApplicationException ex)
{
MessageBox.Show("I am not shown.");
}
}
The window has a Loaded event subscribed in the xaml like this:
<Window x:Class="Stackoverflow.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Loaded="Window_Loaded">
<Grid />
</Window>
An exception is thrown in the Window_Loaded event
private void Window_Loaded(object sender, RoutedEventArgs e)
{
throw new ApplicationException();
}
However the exception is not catched by the catch around the ShowDialog call, nor does the call return. The exception is swallowed and the window still displayed.
Why does this happen and how would I go about handling an exception in the Window_Loaded event of a WPF window? Do I have to catch it in the event-handler and Dispose the window manually?
In WinForms you need to call Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)
in order to let exceptions bubble through ShowDialog calls. Is there a similar switch that needs to be set on WPF?
I've only seen this issue on x64 machines, with code compiled with Any Cpu.
Changing your program to compile as x84 may fix it, but I've had problems there myself depending on our assemblies.
My only code suggestion is the following, and even then it's not guaranteed to pick it up.
Catch the exception, and re-throw it in a Background worker.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
/// your code here...
throw new ApplicationException();
/// your code here...
}
catch (Exception ex)
{
if (IntPtr.Size == 8) // 64bit machines are unable to properly throw the errors during a Page_Loaded event.
{
BackgroundWorker loaderExceptionWorker = new BackgroundWorker();
loaderExceptionWorker.DoWork += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { runWorkerCompletedEventArgs.Result = runWorkerCompletedEventArgs.Argument; });
loaderExceptionWorker.RunWorkerCompleted += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { throw (Exception)runWorkerCompletedEventArgs.Result; });
loaderExceptionWorker.RunWorkerAsync(ex);
}
else
throw;
}
}
The "Why" is explained here: http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/
In short, the exception cannot be propagated in 64-bit operating systems because there is a transition between user and kernel mode.
The test of IntPtr.Size in #midspace answer is not adequate because IntPtr.Size will be equal to 4 in an x86 process running on a x64 os (you need to use Environment.Is64BitOperatingSystem instead on .NET 4 and greater).
The solution now: use another event like ContentRendered which is called after the Loaded one or put your code in the window constructor.
Never use Loaded (or OnLoad in Winforms), because if there is an exception there, you don't know what can happens.
Have a look also at this answer: https://stackoverflow.com/a/4934010/200443
I also reconstructed your answer in Visual Studio 2010 in a blank WPF 3.5 project.
The project behaved as expected, i.e. the Window_Loaded threw the exception, and it was caught by the button click event.
So I'm not sure why yours isn't working, maybe try posting your App.xml.cs and any other code you haven't shown here?
In the meantime, I thought I would point out a few things:
WPF does indeed handle "uncaught" exceptions a little differently from WinForms. Try looking at this for a starter:
http://msdn2.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx
It looks as if there isn't an exact equivalent in WPF for the SetUnhandledExceptionMode method (See http://social.msdn.microsoft.com/forums/en-US/wpf/thread/955c75f8-9cd9-4158-bed9-544bd7946413). Try their advice about registering a handler and see if that helps you?
I would recommend stepping through your code - set a breakpoint in the Window_Loaded, and see what happens - pay careful attention to the call stack.
Good luck!
Researching this a bit more I found this peculiar blogg entry describing a similar problem.
http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/
As it turns out it might be a 64-bit processor architecture problem. Who would have guessed?! It might explain why some people could not reproduce the issue my simple example. I tried to compile my example in "Any CPU", x64 and x86 but to no avail. On x64 the whole thing actually blew up completely crashing with a windows crash dialog.
So I guess this is the answer without verifying it on a 32-bit machine.
I've had similar problem, and trying to understand where it's coming is frustrating. There's a couple of things that could be causing a problem.
Are you calling anything before the method call InitializeComponent(); ? Previously I've had a method calling xaml elements, which haven't been initialised yet.
Have you tried pressing F10 to start the application, using Step Over will let you see the exact process start up?
Have you checked your naming? XAML can swallow errors such as methods being mis-spelt, and then an exception is thrown on run time, this particularly true DataSet providers. You'd be surprised what you can get away with.
Catching an exception for opening a form is pretty fundamental, I'd rather look at any dependents (Data or XAML bindings) and deal with those first.
Hope those points help.......
Related
I have a window with a textbox that is not throwing textInput events when typing.
I have been looking at it with Snooper. Only the KeyDown and KeyUp events get thrown.
It IS responding to a few keys: Space, backspace, Insert, home, delete, end
It responds to copy & paste commands, as well as Select All
It is NOT responding to any character, symbol or number
And here's the kicker: This window is opened via a shared method that is called from two different places in the code. When called from one location the textbox works perfectly, when called from other location it doesn't.
I have ruled out binding, data converters, styles, control location.
I stripped the window down to just a single plain textbox with no bindings, and the problem persists.
I've tried all I can think of to track down this mysterious bug. I can't see what could be handling my event before the previewTextInput even gets throw, or why it could possibly be only occurring half the time.
Any ideas about the cause of this bug, or other tools I could try to trace the events would be greatly appreciated!
Edit: Adding some code to demonstrate. This has been stripped down to the barest code required, and the issue is still occurring.
<Window x:Class="EventViewEmail"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="880" Height="600">
<TextBox VerticalAlignment="Top"/>
</Window>
notice the lack of bindings, styles, or anything else that may be interfering the control
Public Class EventViewEmail
'all code removed from the view-behind'
End Class
this is the static class that builds the window. The two separate calls to this class build the arguments differently. I've removed the code that uses the arguments to show that they aren't affecting the issue at hand.
Public Class EventManager
Public Shared Sub Show(e As EventEdit, p As WorkplanPageViewModel)
Dim w = New EventViewEmail
If w Is Nothing Then Return
'removed datacontext for testing'
'w.DataContext = e '
'w.Tag = p'
w.Show()
End Sub
End Class
The only other thing I can add is that the code calling the Show() sub are coming from two separate solutions. Not sure what impact that could possibly have after I've removed all the arguments
Edit 2:
I have been trying to trace the events sequence to narrow down where the event is getting handled. So far I can see that between the keyDown and keyUp events, there is a sequence of events that should be happening that isn't:
PreviewInputReport / InputReport (no source)
PreviewTextInputStart / TextInputStart (textbox)
PreviewTextInput / TextInput (textbox)
PreviewInputReport / InputReport (textboxView)
the keydown event isn't being handled, so I'm not sure why the PreviewInputReport is not getting fired
Disclaimer
I'll post C# code because I'm not fluent enough in VB to write code (only to read it in a limited scope). I'll try to translate it if I find some time, or anyone of you can feel free to do it.
I have managed to reproduce the behavior you described by handling the PreviewTextInput event up the visual tree on the window (remember it's a tunneling routed event):
<Window (...)>
<StackPanel>
<TextBox x:Name="myTextBox"></TextBox>
</StackPanel>
</Window>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
PreviewTextInput += (s, e) => e.Handled = true;
}
}
So in my opinion it's a strong suspect for the cause of your problems. It also explains the comment to #AQuirky's answer that your PreviewTextInput handler is not called. You can confirm that that's the case by subscribing differently (the handler is called even if the event was marked as handled):
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
PreviewTextInput += (s, e) => e.Handled = true;
myTextBox.AddHandler(
routedEvent: PreviewTextInputEvent,
handler: new TextCompositionEventHandler((s, e) =>
{
if (e.Handled)
throw new Exception("Gotcha!");
}),
handledEventsToo: true);
}
}
If this turns out to be correct diagnosis, then there's one thing that's somewhat mysterious - who and where does handle the PreviewTextInput event? I guess that's for you to investigate...
This comment from #l33t might come in handy:
Look for global event handlers like EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewTextInputEvent, ...) and/or behaviors. Are you using any third-party UI library? Look in their code as well.
Update
Since it seems like PreviewTextInput is not the culprit after all, here's what I'd do next.
If I'm not mistaken, there's a whole chain of events being fired prior to TextInputEvent, and I believe handling any of those can break the chain. It also looks like InputManager is responsible for managing this event cycle (you can inspect its C# source code here).
That being said I suggest doing the following:
Using InputManager.Current subscribe to its PreProcessInput and/or PostProcessInput events (optionally also PreNotifyInput and PostNotifyInput)
Record the events chain in the working scenario (especially inspect the args' StagingItem.Input.RoutedEvent, which holds the routed event currently being processed)
Repeat the procedure for the not working scenario
Pinpoint the first difference - the first routed event being processed in the working scenario, but not being processed in the not working scenario
Investigate both last common routed event and the first one that's different - perhaps one of those is handled in your code?
In this case it turned out that the form that launched the window in the not working case was a winform. The winform was blocking the keystrokes. This was fixed by opening the window as a modal.
I had the same problem here. The difference between the two calls was: one time the WPF-Windows was called modal (works) and one time nonmodal (doesnt work), everytime from a WindowsForms Window.
As Shaboboo wrote in his anwer, this is the difference, but what, if you need to call nonmodal.
The answer is given this thread. (stupid me, I had the same problem 2 years ago, asked and got an answer). We have to use
ElementHost.EnableModelessKeyboardInterop(wpfWindow);
Thanks again to V.Leon
The problem is that while the TextInput is being fired (not thrown...exceptions are thrown) you are not seeing it because the text box itself is using it. To catch this event you need to use the PreviewTextInput. So for example
<TextBox TextInput="UIElement_OnTextInput" PreviewTextInput="UIElement_OnPreviewTextInput"></TextBox>
With event handlers...
private void UIElement_OnTextInput(object sender, TextCompositionEventArgs e)
{
Console.WriteLine($"In text input event, {e.Text}");
}
private void UIElement_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
Console.WriteLine($"In preview text input event, {e.Text}");
}
The first handler is never called, the second one always.
Your handler is not called because other handlers have marked the event as handled. You can add an handler with AddHandler() and pass true for the third argument:
public MainWindow()
{
var handler = new RoutedEventHandler(OnTextInput);
myTextBox.AddHandler(TextInputEvent, handler, handledEventsToo: true);
}
private static void OnTextInput(object sender, RoutedEventArgs e)
{
}
I'm trying to create a simple global exception handler in a WPF application that is build with the MVVM Light Toolkit, but I'm having a hard time making it work.
The thing is that an exception risen in a view model will not be caught in the App's UnhandledException handler, even though I register a listener for both the Dispatcher and the AppDomain like this:
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += DomainUnhandledException;
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private void DomainUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
var exception = unhandledExceptionEventArgs.ExceptionObject as Exception;
ShowExceptionMessage(exception);
}
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
ShowExceptionMessage(e.Exception);
e.Handled = true;
}
I found this blog post that describes the problem spot on, with the solution described with this code snipped for view models:
// Throw the exception in the UI thread.
App.Current.RootVisual.Dispatcher.BeginInvoke(() => { throw new MyException(); });
However, I would like all exceptions to bubble up to the global exception handler, not only the ones that I throw myself in the VM.
So the question is: Is it somehow possible to re-throw exceptions from other threads into the UI thread in one place?
Update: Added more detailed code for the App's event handler setup.
I think I figure this out now.
The problem is due to the fact that WPF suppresses exceptions thrown in a view's databinding, and because my view model is databound to the view's DataContext (through a property in my ViewModelLocator utilizing unity dependency injector) any exceptions in the construction of the view model will be swallowed.
See this SO question for more info.
So I suppose I just have to make sure that nothing important for the application's ability to function correctly should happen in the constructor.
The “global” exception handling events for WPF and Windows Forms applications (Application.DispatcherUnhandledException and Application.ThreadException) fire only for exceptions thrown on the main UI thread. You still must handle exceptions on worker threads manually.
AppDomain.CurrentDomain.UnhandledException fires on any unhandled exception, but provides no means of preventing the application from shutting down afterward.
Maybe check also Thread Pooling “divide-and-conquer” style.
TPL
How do I invoke a method on the UI thread when using the TPL?
I'm trying to implement binding validation using Silverlight on Windows Phone, but all I get is the debugger breaking on an unhandled exception instead, and the validation not happening.
I'm following the recommendations from an MSDN article on Data Binding.
Here is what I have tried to do to set it up:
Debug -> Exceptions -> Common Language Runtime Exceptions - User-unhandled is unchecked
On the data template for the ListBoxItem, I declare two-way binding with validations:
<TextBox x:Name="LastReadingValue" Text="{Binding LastReadingValue, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
In the setter I raise an exception if the TextBox data is incorrect:
public string LastReadingValue
{
get
{
return _lastReadingValue;
}
set
{
try
{
double reading = System.Convert.ToDouble(value);
_lastReadingValue = String.Format("{0:0.00}", reading);
}
catch (FormatException fe)
{
throw new Exception("The meter reading must be a number like 7561.41");
}
NotifyOfPropertyChanged("LastReadingValue");
}
}
On the ListBox I declare the handler for the BindingValidationError event:
<ListBox x:Name="NewMeterReadingsListBox" ItemsSource="{Binding Meters}" ItemTemplate="{StaticResource NewMeterReadingDataTemplate}" BindingValidationError="ListBox_BindingValidationError"/>
The handler for the BindingValidationError never gets called:
private void ListBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
Debug.WriteLine("BindingValidationError");
}
Ok - 2nd try at an answer.
A couple of interesting things happened when I tried this myself. I started from the WindowsPhoneDataboundApplication then added a TextBox and validation to the app's ListBox. I'm using the WP Mango Beta 2 tools (not the Beta 2 update from yesterday).
When debugging: if an invalid value is entered I get a debug break and prompt from VS on the throw line says that the exception is unhandled. HOWEVER: the BindingValidationError handler is called fine, the application keeps running and Application.UnhandledException isn't called.
In the _BindingValidationError function the Debug.WriteLine text is often difficult to spot with the other exception text in the output window. If you make it more obvious by forcing a new line you should spot the text:
Debug.WriteLine("\n\n*** BindingValidationError ***\n");
So basically it's working for me, but there are a couple of things to watch out for when debugging.
If you're targetting WP Mango I'd recommend you consider the Silverlight 4 way of doing data validation which doesn't involve throwing and catching exceptions - I agree with Claus insofar as using exceptions is a really ugly way of doing validation. The SL4 alternative involves implementing the IDataErrorInfo and INotifyDataErrorInfo interfaces in your bound class. I haven't tried this approach personally myself though.
Edit:
If you really want to turn off the break on exceptions you can do it from the VS2010 "Debug" menu, "Exceptions" item. Then de-select the exception type you don't want VS to do break on if it is unhandled.
If you create your own custom Exception class just for binding validation and disable the debug break only for that Exception type, then you will be able to have normal VS behaviour for your app's exceptions except when when dealing with binding failures.
I put several ComboBoxes on a XAML window. When I expand any of them, the DropDown part appears on the upper left corner of the screen.
I use Visual Studio 2008 C# Express. I don't remember this phenomenon when I used Visual Studio 2008 (Trial Version), though I use the same FrameWork (3.5).
It seems to be a bug.
Workaround:
Use Window.Show() instead with a custom logic to simulate the ShowDialog() behavior.
This appears to be a bug in WPF. In my case, I was trying to open a window in the Loaded event of another window. To get around this, I set a timer up to fire, then used a delegate to open the window (cannot open the window in a timer event because the calling thread that opens a window must be STA).
Edit - timer isn't necessary - didn't see the answer above just queue it on the dispatcher...
private delegate void DelegateOpenWindow();
private DelegateOpenWindow m_DelegateOpenWindow;
private Timer loginTimer = new Timer(200);
private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
{
// create delegate used for asynchronous call
m_DelegateOpenWindow= new DelegateOpenWindow(this.OpenWindow);
// start a timer to fire off the open window.
loginTimer.Elapsed += loginTimer_Elapsed;
loginTimer.Enabled = true;
}
void loginTimer_Elapsed(object sender, ElapsedEventArgs e)
{
loginTimer.Enabled = false;
this.Dispatcher.BeginInvoke(m_DelegateOpenWindow);
}
void OpenWindow()
{
MyWindow w = new MyWindow();
w.Owner = this;
w.ShowDialog();
}
I started observing this (and other strange behavioral quirks) yesterday when I tried to "tweak" window sizes, shapes, colors, and invoke a log-on dialog from the Window.Loaded event handler. I had been doing this just fine in each of a dozen+ individual "MVVM" pattern apps. Yesterday, I decided to move this from each app's code behind into a consolidated code-behind base class, since the pre-processing had become common in all those apps. When I did, the drop-downs in two ComboBoxes in the log-in dialog suddenly appeared in the upper left corner of my screen. I seem to have "solved" it by using the following technique (your mileage may vary):
protected void WindowBaseLoadedHandler(object sender, RoutedEventArgs e)
{
...non-essential lines of code removed...
if (DataContext != null)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
/*----------------------------------------------------------------------
* Do we have a View Model? If so, perform standard VM Initialization...
*---------------------------------------------------------------------*/
this.IsEnabled = false;
LoginDlg loginDlg = new LoginDlg();
loginDlg.ShowDialog();
if (!loginDlg.Success)
{
/*-----------------------------------
* Log on failed -- terminate app...
*----------------------------------*/
...termination logic removed...
}
this.IsEnabled = true;
}));
}
WindowBaseLoadedHandler is the Loaded event handler. LoginDlg is a WPF app with a dialog containing two ComboBoxes.
Recap: After I consolidated the code into the Loaded event handler of the base class the ComboBox's drop down lists appeared in the upper left corner of my screen. Once I wrapped the logic into the Dispatcher.BeginInvoke call, the appropriate ComboBox behavior returned with lists below the current item.
I suspect WPF needs the application to return from the Loaded event to complete the layout system's initialization. That doesn't fully explain why it worked before, but I'll have to queue up my desire to hunt that "why" down for some rainy day in the future and celebrate overcoming the latest obstacle for today.
In any event, I hope someone finds this of use.
I'm using the latest .Net 4.5 and WPF framework and I still have this problem. One thing I noticed is that it only happen when there's an attached debugger. When the debugger is not attached, everything works fine.
I had the same problem on Visual Studio 2019.
Using window.Show() can help but it can ruin your design.
The solution is to open the window asynchronously.
var yourDialog= new YourDialog();
yourDialog.Owner = this;
TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
this.Dispatcher.BeginInvoke(new Action(() =>
completion.SetResult(yourDialog.ShowDialog())));
bool? result = await completion.Task;
You can also create a more elegant solution by making the extension method:
public static class AsyncWindowExtension
{
public static Task<bool?> ShowDialogAsync(this Window self)
{
if (self == null) throw new ArgumentNullException("self");
TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
self.Dispatcher.BeginInvoke(new Action(() => completion.SetResult(self.ShowDialog())));
return completion.Task;
}
}
And you can use it like this:
await dlgReview.ShowDialogAsync();
It’s a bug in WPF (not the only one, I'm afraid). It happened when I opened another window in the Loaded Event, something like:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Window selectionWindow = new SelectionWindow();
bool? result = selectionWindow.ShowDialog();
if (result == true)
RecordChanged();
}
I already found a workabout.
Issue:
Our application crashes when a user type some text into the WPF TextBox.
Please help! The easy 3 minutes reproduction appears below
Reproduction:
Register a WPF TextBox (m_textBox) TextChanged event to the method below
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// This line of code throws Unhandled exception when typing '^' char in
// the text box (in United "States-International" keyboard)
m_textBox.Dispatcher.Invoke(DispatcherPriority.Normal, new SendOrPostCallback(Foo), null);
}
private void Foo(object state)
{
//Do nothing
}
Change your keyboard to "United States - International"
Run the application and type '^' twice in the TextBox
Aplication will crash!!!!
The problem is the composition code doesn't expect to get additional input events until your TextChanged handler returns. When you call Dispatcher.Invoke, it causes the Windows message queue to be processed causing additional input events.
In my opinion this is a bug because the composition engine should be robust against re-entrancy when firing user-specified events.
I could reproduce this error. Typing ^q or ~~ will also cause the crash.
The exception that is thrown states that composition has already been completed. I managed to work around it by using the async BeginInvoke instead of Invoke. Will that work for you?
m_textBox.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new SendOrPostCallback(Foo), null);