Возможно, я неправильно использую OpenFileDialog
, но я обнаружил, что необработанные исключения подавляются всякий раз, когда используется OpenFileDialog
, и результат передается в мою модель.
Обычно я подключаю событие AppDomain.CurrentDomain.UnhandledException
для обработки любых необработанных исключений, но любые исключения, возникающие после использования OpenFileDialog
, проглатываются целиком.
Ниже приведен пример для воспроизведения этого поведения. Если вы запустите пример, вы увидите, что исключения, создаваемые в коде и свойстве ShellModel.ThrowException
, корректно перехватываются обработчиком UnHandledException
в App.xaml.cs. Однако исключение, которое выдается в свойстве ShellModel.OpenFile
после использования OpenFileDialog
, подавляется.
Почему бы исключить эти исключения?
App.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 );
}
}
}
Shell.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, а проблема привязки данных.
Ответ Брэдли и возможная двойная ссылка Ганса указали на некоторую полезную информацию Ссылки / статьи не совсем обеспечивают разрешение, которое я придумал, re: я обнаружил, что есть еще одно исключение, в которое я могу зацепиться: 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
}
Ошибки привязки теперь обнаруживаются!