也许我使用OpenFileDialog
不正确,但我发现每当OpenFileDialog
使用 并将结果传递到我的模型时,都会抑制未处理的异常。
通常,我会在事件中挂钩AppDomain.CurrentDomain.UnhandledException
以处理任何未处理的异常,但在使用后引发的任何异常都会被OpenFileDialog
整个吞下。
以下是重现此行为的示例。如果您运行该示例,您将看到在后面的代码中引发的异常和属性被App.xaml.cs 中ShellModel.ThrowException
的处理程序正确捕获。但是,使用 后在属性UnHandledException
中引发的异常被抑制。ShellModel.OpenFile
OpenFileDialog
为什么要抑制这些异常?
应用程序.xaml.cs
using System;
using System.Text;
using System.Windows;
namespace ExceptionTest
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup( StartupEventArgs e )
{
base.OnStartup( e );
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
}
private void OnUnhandledException( object sender, UnhandledExceptionEventArgs e )
{
var ex = e.ExceptionObject as Exception;
if( ex == null )
{
MessageBox.Show( string.Format( "Null Exception: {0}", e ) );
return;
}
var sb = new StringBuilder();
sb.AppendLine( "An unhandled exception was encountered. Terminating now." );
sb.AppendLine();
sb.AppendLine( "Exception:" );
sb.AppendLine( ex.Message );
MessageBox.Show( sb.ToString(), "Whoops...", MessageBoxButton.OK, MessageBoxImage.Error );
Environment.Exit( 1 );
}
}
}
壳牌.xaml
<Window x:Class="ExceptionTest.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Model="clr-namespace:ExceptionTest"
Title="Exception Test" Height="350" Width="350" WindowStartupLocation="CenterScreen">
<Window.DataContext>
<Model:ShellModel x:Name="Model" />
</Window.DataContext>
<StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
<Button
Click="OnCodeBehind" Margin="20"
Content="Exception from code behind" Height="25" Width="250" />
<Button
Click="OnThrowExeption" Margin="20"
Content="Exception from Model" Height="25" Width="250" />
<Button
Click="OnFindFile" Margin="20"
Content="Exception from OpenFileDialog" Height="25" Width="250" />
<Label Content="{Binding OpenFile, Mode=TwoWay}" x:Name="OpenFile"
Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="Auto" />
</StackPanel>
</Window>
Shell.xaml.cs / 模型
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Windows;
using Microsoft.Win32;
namespace ExceptionTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class Shell : Window
{
private OpenFileDialog OpenDialog { get; set; }
public Shell()
{
InitializeComponent();
OpenDialog = new OpenFileDialog();
string path = new Uri( Assembly.GetExecutingAssembly().CodeBase ).LocalPath;
OpenDialog.InitialDirectory = Path.GetDirectoryName( path );
OpenDialog.Multiselect = false;
OpenDialog.Title = "Find File";
OpenDialog.RestoreDirectory = true;
}
private void OnCodeBehind( object sender, RoutedEventArgs e )
{
throw new Exception( "Exception from Code Behind." );
}
private void OnThrowExeption( object sender, RoutedEventArgs e )
{
Model.ThrowException = "Test";
e.Handled = true;
}
private void OnFindFile( object sender, RoutedEventArgs e )
{
OpenDialog.ShowDialog( this );
string fileName = OpenDialog.FileName;
if( !string.IsNullOrEmpty( fileName ) )
{
OpenDialog.InitialDirectory = Path.GetDirectoryName( fileName );
OpenFile.Content = fileName;
}
}
}
public class ShellModel : INotifyPropertyChanged
{
private string _throwException;
public string ThrowException
{
get { return _throwException; }
set
{
_throwException = value;
NotifyPropertyChanged( "ThrowException" );
throw new Exception( "Exception from Model." );
}
}
private string _openFile;
public string OpenFile
{
get { return _openFile; }
set
{
_openFile = value;
NotifyPropertyChanged( "OpenFile" );
throw new Exception( "Exception from Model after using OpenFileDialog." );
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged( String info )
{
if( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( info ) );
}
}
}
}
解析度
如答案中所述,这不是 OpenFileDialog 问题,而是数据绑定问题。
布拉德利的回答和汉斯可能的重复链接指向了一些重要的信息。链接/文章并没有完全提供我想出的解决方案,回复:我发现还有另一个我可以挂钩的异常:AppDomain.CurrentDomain.FirstChanceException
这是我的修改版本App.Xaml.cs
:
protected override void OnStartup( StartupEventArgs e )
{
base.OnStartup( e );
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
// The FirstChanceException will catch binding errors
AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
}
private void OnFirstChanceException( object sender, FirstChanceExceptionEventArgs e )
{
// do stuff
}
现在已捕获绑定错误!