2

ViewModelでスローされた例外が、App.xaml.csのApplication_UnhandledExceptionにバブルアップしない次の状況があります。

ComboBoxのItemSourcePropertyにバインドされたViewModelにObservableCollectionがあります。ComboBoxのSelectedItemPropertyは、ViewModelのプロパティにバインドされています。

ユーザーがComboBoxのエントリを選択すると、ViewModelでプロパティが正しく呼び出されます。少しロジックが実行され、別のプロパティ(property2と呼ばれます)がViewModelに設定されます。ただし、property2には未処理の例外があります。例外は単に「消える」だけで、UIスレッドでは発生しません。

この問題を一般的に修正する方法や、スレッドの例外をキャッチする方法についての提案はありますか?

カスタムビルドのMVVMフレームワークがあることに注意してください。最初は、フレームワークの問題だと思いました。何時間もデバッグした後、Prism4(http://www.microsoft.com/download/en/confirmation.aspx?id=4922)をダウンロードして、StockTraderリファレンスアプリケーションで同様のシナリオを再現できるかどうかを確認することにしました。

まったく同じシナリオを再現できます!Prism4で例外を設定する方法の詳細を提供させていただきます。

Silverlightで未処理のすべての例外をキャッチするための一般的なアプローチに関するヘルプやポインタは、大歓迎です。

よろしく、トラビス

4

2 に答える 2

2

ランタイムでは検証目的で例外を使用できるため、ランタイムのバインディング値の取得操作は1つの大きな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 に答える