Исключение Silverlight во ViewModel не обнаружено в Application_UnhandledException - PullRequest
2 голосов
/ 06 декабря 2011

У меня есть следующая ситуация, когда исключение, генерируемое в ViewModel, не всплывает до Application_UnhandledException в App.xaml.cs.

У меня есть ObservableCollection в ViewModel, привязанная к ItemSourceProperty в ComboBox. Свойство SelectedItemProperty объекта ComboBox привязывается к свойству в модели представления.

Когда пользователь выбирает запись в ComboBox, свойство корректно вызывается во ViewModel. Немного логики выполняется, и другое свойство (назовите его property2) устанавливается в ViewModel. Однако есть необработанное исключение в property2. Исключение просто «исчезает» - оно не вызывается в потоке пользовательского интерфейса.

Какие-либо предложения о том, как вообще решить эту проблему или подход к перехвату исключений в любом потоке?

Обратите внимание, что у нас есть пользовательский фреймворк MVVM. Сначала я думал, что это проблема с нашей структурой. После многих часов отладки я решил загрузить Prism4 (http://www.microsoft.com/download/en/confirmation.aspx?id=4922)) и посмотреть, можно ли воспроизвести подобный сценарий в справочном приложении StockTrader.

Я могу воспроизвести точно такой же сценарий! Я был бы рад предоставить подробную информацию о том, как настроить исключение в Prism4.

Любая помощь или указатели по общему подходу для отлова ВСЕХ необработанных исключений в Silverlight приветствуются.

С уважением, Travis

Ответы [ 2 ]

2 голосов
/ 06 декабря 2011

Поскольку среда выполнения позволяет вам использовать исключения для целей проверки, операция get-value-for-binding среды выполнения находится в одном большом блоке try-catch.

Посмотрите подробности на System.Windows.Data.BindingExpression.UpdateValue () в ILSpy (в System.Windows. Версия WPF может быть проще для понимания (UpdateSource)).

Я не думаю, что можно настроить поведение среды выполнения, чтобы перебрасывать ваши собственные исключения. Из кода видно, что он отбрасывает некоторые критические.

   OutOfMemoryException, StackOverflowException, AccessViolationException, ThreadAbortException

Поскольку другие исключения не перебрасываются, они фактически обрабатываются.

Я думаю, что ваше решение - либо захватить трассировку, либо иметь собственную обработку исключений в установщиках свойств.

0 голосов
/ 13 мая 2014

Недавно я нашел способ перехвата всех исключений привязки во всех установщиках свойств (работает в 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);
    }
}
...