Ensure that exceptions from ActiveItem are rethrown

Conductor<T>.Collections.OneActive has its ActiveItem set from a binding
in most cases. However, bindings swallow exceptions encountered when
setting the source. This means that the user switched to a new
ViewModel, and its OnActivate/OnInitialActivate method threw an
exception (or the OnDeactivate method of the ViewModel being switched
away from threw an exception), this exception would be swallowed by the
binding.

Work around this by introducing RethrowingBinding, which explicitly
rethrows any exceptions encountered when setting the source on the
dispatcher. Use this for the ActiveItem binding on
StyletConductorTabControl.

Fixes #133
This commit is contained in:
Antony Male 2020-06-20 11:51:02 +01:00
parent c6224952ec
commit 529cd140ee
2 changed files with 33 additions and 1 deletions

View File

@ -0,0 +1,32 @@
using System;
using System.Runtime.ExceptionServices;
using System.Windows.Data;
namespace Stylet.Xaml
{
/// <summary>
/// <see cref="Binding"/> subclass which rethrows exceptions encountered on setting the source
/// </summary>
public class RethrowingBinding : Binding
{
/// <inheritdoc/>
public RethrowingBinding()
{
this.UpdateSourceExceptionFilter = this.ExceptionFilter;
}
/// <inheritdoc/>
public RethrowingBinding(string path)
: base(path)
{
this.UpdateSourceExceptionFilter = this.ExceptionFilter;
}
private object ExceptionFilter(object bindExpression, Exception exception)
{
var edi = ExceptionDispatchInfo.Capture(exception);
Execute.OnUIThread(() => edi.Throw());
return exception;
}
}
}

View File

@ -3,7 +3,7 @@
xmlns:s="clr-namespace:Stylet.Xaml">
<Style x:Key="StyletConductorTabControl" TargetType="TabControl">
<Setter Property="ItemsSource" Value="{Binding Items}"/>
<Setter Property="SelectedItem" Value="{Binding ActiveItem}"/>
<Setter Property="SelectedItem" Value="{s:RethrowingBinding ActiveItem}"/>
<Setter Property="DisplayMemberPath" Value="DisplayName"/>
<Setter Property="ContentTemplate">
<Setter.Value>