Просто стрельба с бедра.Возможно, самый простой способ отловить исключения при инициализации - это разрешить доступ к вашему агрегатору событий через одноэлементный файл и вызвать событие из представления.
Однако после запуска приложения, если вы хотите обрабатывать необработанные исключения в потоке пользовательского интерфейса без сбоя приложения, вы можете попробовать событие Application.UnhandledException .Это позволяет обрабатывать исключение в Silverlight или WPF и обрабатывать его, а затем либо отменить, либо продолжить, чтобы исключение исключило вас из приложения.
Отказ от ответственности: весь непроверенный код, как при компиляции, так и при выполнении
public class MyView : UserControl
{
public MyView()
{
// Hardly best practice, but it'll work
try
{
InitializeComponent();
}
catch(Exception caught)
{
EventAggregatorService.Instance.GetEvent<XamlExceptionEvent>().Publish(/* ... */);
}
}
}
public class EventAggregatorService
{
public IEventAggregator Instance { get { return _instance; } }
// NOTE: Must be called once in your bootstrapper to set the EA instance
public static void SetEventAggregator(IEventAggregator instance)
{
_instance = instance;
}
}
Если вы сможете создать базовую модель вида, подобную этой,
, сделайте еще один шаг вперед
// Base viewmodel type to handle errors
public abstract class ErrorViewModel
{
private IEventAggregator eventAggregator;
protected ErrorViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public void HandleInitializationException(object view, Exception caught)
{
// Publish event via _eventAggregator
}
}
Если модели производных представлений определены следующим образом
// Derived viewmodel type
public class DerivedViewModel : ErrorViewModel
{
public DerivedViewModel (IEventAggregator eventAggregator) : base(eventAggregator)
{
}
}
Вы можете применить следующий метод к вашему представлению следующим образом, перехватывая исключение и откладывая обработку ошибок.
public class MyView : UserControl
{
private readonly Exception _ex;
public MyView()
{
try { InitializeComponent(); } catch (Exception caught) { _ex = caught; }
}
protected override OnDataContextChanged(object sender, EventArgs e)
{
if (_ex == null) return;
var vm = view.DataContext as ErrorViewModel;
if (vm != null)
{
vm.HandleInitializationException(view, caught);
return;
}
throw new Exception("Error occurred during View initialization", _ex);
}
}
Хорошо, это не аккуратно и не красиво, но опять-таки это сработает.Сделав еще один шаг вперед, вы можете создать базовый тип представления, чтобы исключить инициализацию, однако, если вы наследуете несколько различных базовых типов, это вам не поможет.В качестве альтернативы класс справки, чтобы отложить инициализацию, вызывая метод Initializecomponent()
через отражение.
Наконец, код для обработки UnhandledException:
public partial class App : Application
{
public App()
{
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
private void Application_UnhandledException(object sender,
ApplicationUnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is FileNotFoundException)
{
// Inform the user
EventAggregatorService.Instance.GetEvent<MyUnhandledExceptionEvent>().Publish(/* ... */);
// Recover from the error
e.Handled = true;
return;
}
}
Просто некоторые идеи.Мне было бы интересно услышать, есть ли решение де-факто для этого, поскольку я часто сталкивался с этой проблемой!
С уважением