MVVM中的全局异常处理

本文关键字:异常处理 全局 MVVM | 更新日期: 2023-09-27 18:13:12

是否有办法实现MVVM模式的全局异常处理。在我现有的情况下,无论何时ViewModel内部发生错误,应用程序都不会崩溃,只是"隐藏"了在导致错误的代码之后发生的其余绑定(当然这对最终用户来说是非常误导的,并且不正确,并且不应该以这种方式发生)。我不想为viewModel中的每个操作实现try catch,我不喜欢错误异常的沉默方式,我真的很想实现一种WPF应用程序处理全局错误的方式。有办法做到这一点与MVVM吗?

MVVM中的全局异常处理

经过长时间的战斗,我终于找到了一种非常简单的方法来实现ViewModel内部的异常处理。虽然创建从DefaultTraceListener继承的BindingListener当然是在调试模式中发现绑定错误的好方法,但这将无法捕获在标准模式下运行解决方案时在ViewModel中发生的异常。但是AppDomain.CurrentDomain.FirstChanceException会。

App.xaml.cs:

AppDomain.CurrentDomain.FirstChanceException += new EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>(CurrentDomain_FirstChanceException);

    private void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
    {
            Dispatcher.BeginInvoke(new Action(() => MessageBox.Show("Error Occurred 'n'r" + e.Exception.Message + "'n'r" + e.Exception.StackTrace, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error)));
    }

您可以将每个方法包装在一个lambda中。像这样…

        public async void DoSomething()
        {
            await RunSafe(async () =>
            {
                await model.DoSomething();
                await model.DoSomethingElse();
                await model.DoLastThing();
            });
        }
        private async Task RunSafe(Func<Task> del, [CallerMemberName] String methodName = "")
        {
            try
            {
                Log.Info("Executing {0}", methodName);
                await del();
            }
            catch (Exception ex)
            {
                StatusMessage = string.Format("Error in {0}(...): {1}'r'n{2}", methodName, ex.Message, ex.ToString());                
                Log.Error("Error occured in plug in.", ex);
            }
        }

考虑派生DefaultTraceListener类。我看到有人从它派生出自己的BindingListener,并覆盖WriteLine方法来抛出自己的异常。

你可以在应用程序启动时启动其中一个,它应该自己运行:

public class BindingListener : DefaultTraceListener`
{
    public BindingListener()
    {
        PresentationTraceSources.Refresh();
        PresentationTraceSources.DataBindingSource.Listeners.Add(this);SourceLevels.Error;
    }
    public override void WriteLine(string message){...}
}

注意:这个可能不完全是你想要的,你可能需要修改一些道具