ViewModel中的Silverlight异常未在Application_UnhandledException中捕获

时间:2011-12-06 02:40:36

标签: silverlight exception mvvm unhandled

我遇到以下情况:ViewModel中抛出的异常未冒泡到App.xaml.cs中的Application_UnhandledException。

我在ViewModel中有一个ObservableCollection绑定到ComboBox中的ItemSourceProperty。 ComboBox的SelectedItemProperty绑定到ViewModel中的属性。

当用户在ComboBox中选择一个条目时,在ViewModel中正确调用该属性。执行一些逻辑,并在ViewModel中设置另一个属性(称为property2)。但是,property2中存在未处理的异常。异常只是“消失” - 它不会在UI线程上引发。

有关如何一般性地修复此问题或在任何线程上捕获异常的方法的任何建议?

请注意,我们有一个自定义构建的MVVM框架。起初,我认为这是我们框架的一个问题。经过几个小时的调试,我决定下载Prism4(http://www.microsoft.com/download/en/confirmation.aspx?id=4922),看看是否可以在StockTrader参考申请中复制类似的场景。

我可以重现完全相同的场景!我很乐意提供有关如何在Prism4中设置异常的详细信息。

非常感谢任何关于在Silverlight中捕获所有未处理异常的一般方法的帮助或指示。

此致 特拉维斯

2 个答案:

答案 0 :(得分:2)

由于运行时允许您使用异常进行验证,因此运行时的get-value-for-binding操作位于一个大的try-catch块中。

查看ILSpy中的System.Windows.Data.BindingExpression.UpdateValue()了解详细信息(在System.Windows中.WPF版本可能更容易理解(UpdateSource))。

我认为不可能自定义运行时的行为来重新抛出自己的异常。您可以从代码中看到它重新抛出了一些重要的东西。

   OutOfMemoryException, StackOverflowException, AccessViolationException, ThreadAbortException

由于没有重新抛出其他异常,事实上它们已被处理。

我认为您的解决方案是捕获跟踪,或者在属性设置器中进行自己的异常处理。

答案 1 :(得分:0)

最近我找到了如何捕获所有属性设置器中的所有绑定异常的方法(适用于Silverlight 5):

public class Helper
{
    public static void EnableBindingExceptions(FrameworkElement element)
    {
        const BindingFlags flags = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static;
        var fields = element.GetType().GetFields(flags).Where(x => x.FieldType == typeof(DependencyProperty));
        foreach (var field in fields)
        {
            var dp = (DependencyProperty)field.GetValue(null);
            var be = element.GetBindingExpression(dp);
            if (be == null) continue;

            element.SetBinding(dp, new Binding(be.ParentBinding) {ValidatesOnExceptions = true, ValidatesOnNotifyDataErrors = true});
            element.BindingValidationError += OnBindingValidationError;
        }

        var childrenCount = VisualTreeHelper.GetChildrenCount(element);
        for (var i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
            if (child == null) continue;

            EnableBindingExceptions(child);
        }
    }

    private static void OnBindingValidationError(object sender, ValidationErrorEventArgs e)
    {
        throw new TargetInvocationException(e.Error.Exception);
    }
}

然后只为每个视图调用EnableBindingExceptions方法:

public partial class MyView : UserControl
{
    public MyView()
    {
        InitializeComponent(); 
        Helper.EnableBindingExceptions(this);
    }
}