2

我有以下情况,其中 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 中捕获所有未处理异常的一般方法的任何帮助或指示。

问候,特拉维斯

4

2 回答 2

2

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

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

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

   OutOfMemoryException, StackOverflowException, AccessViolationException, ThreadAbortException

由于其他异常不会被重新抛出,它们实际上是被处理的。

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

于 2011-12-06T03:20:47.703 回答
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);
    }
}
于 2014-05-13T06:41:26.690 回答