ViewModelのSilverlight Exceptionは、application_unhandledexceptionに巻き込まれていません
-
28-10-2019 - |
質問
viewmodelに投げ込まれた例外がappl.xaml.csでapplication_unhandledexceptionに泡立っていないという次の状況があります。
コンボボックス内のitemsourcePropertyにバインドされたviewmodelに観測可能な収集があります。コンボボックスのSelectedItemPropertyは、ViewModel内のプロパティにバインドされています。
ユーザーがコンボボックス内のエントリを選択すると、ビューモデルでプロパティが正しく呼び出されます。少しロジックが実行され、別のプロパティ(Property2と呼ばれる)がViewModelに設定されています。ただし、Property2には未解決の例外があります。例外は「消える」だけです - UIスレッドでは上げられません。
一般的にこの問題を修正する方法や、どのスレッドで例外をキャッチするアプローチを修正するかについての提案はありますか?
カスタムビルドMVVMフレームワークがあることに注意してください。最初は、それが私たちのフレームワークの問題だと思いました。何時間もデバッグした後、Prism4(http://www.microsoft.com/download/en/confirmation.aspx?id=4922)をダウンロードし、Stocktraderリファレンスアプリケーションで同様のシナリオを再現できるかどうかを確認することにしました。
まったく同じシナリオを再現できます! PRISM4で例外を設定する方法の詳細を提供していただければ幸いです。
Silverlightのすべての未解決の例外をキャッチするための一般的なアプローチに関するヘルプまたはポインターは、非常に高く評価されています。
よろしく、トラビス
解決
ランタイムを使用すると、検証目的で例外を使用できるため、ランタイムのGet-Value-forバインディング操作は1つの大きなトライキャッチブロックにあります。
system.windows.data.bindingexpression.updatevalue()をご覧ください。詳細については(System.Windows。WPFバージョンを理解しやすい場合があります(UpdatesOurce))。
ランタイムの動作をカスタマイズして、独自の例外をreもrethりませんでした。コードから、いくつかの重要なものを蘇らせることがわかります。
OutOfMemoryException, StackOverflowException, AccessViolationException, ThreadAbortException
他の例外はret延していないため、実際には処理されます。
あなたの解決策は、トレースをキャプチャするか、プロパティセッターで独自の例外処理をすることだと思います。
他のヒント
最近、私はすべてのプロパティセッターですべての拘束力のある例外をキャッチする方法を見つけました(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);
}
}
次に、ビューごとにenabableBindingExceptionsメソッドを呼び出します。
public partial class MyView : UserControl
{
public MyView()
{
InitializeComponent();
Helper.EnableBindingExceptions(this);
}
}