Description
Describe the bug 🐞
At least in WPF, you can create a view with some child Visual that has an invalid binding, such that an exception is thrown as soon as DataContext is set on the child Visual.
The bug is that it appears that BindTo
sometimes swallows exceptions.
So, in some circumstances, this binding will swallow an exception:
myView.WhenAnyValue(x => x.ViewModel).DistinctUntilChanged().BindTo(myView, x => x.DataContext);
whereas this binding would throw the exception:
myView.WhenAnyValue(x => x.ViewModel).DistinctUntilChanged().Do(x => myView.DataContext = x).Subscribe();
More details: When you set the DataContext on the View, WPF will walk through the logical children of the View, setting the DataContext on each child, until it encounters the Visual with the invalid binding. This then throws an exception. If the exception is unhandled, the application crashes. If handled, it interrupts the process of enumerating the logical children, thus leaving some children with the new ViewModel and some children with the old ViewModel.
Step to reproduce
See the https://github.com/timothylcooke/BindToSwallowsExceptions/ repository. The readme gives a simple explanation of how to reproduce it. The File Menu has different actions you can do. Five of the six actions throw an exception, but the sixth swallows the exception.
Alternatively:
- Create a View that has a two-way binding to some property, called
MyProperty
. - Create a ViewModel that has a read-only property called
MyProperty
(i.e. private setter). - Set the View's DataContext to some object that does not have a property called
MyProperty
(e.g.myView.DataContext = new object()
). - Change the View's DataContext to the ViewModel with the read-only property.
Step 4 above will throw an exception that you can't have a two-way binding to a read-only property. If you did step 4 with a .BindTo(view, x => x.DataContext)
, then the exception will be swallowed. The only way you would know it threw is if you check the Debug output or notice that some child controls in the View have the wrong DataContext.
Reproduction repository
https://github.com/timothylcooke/BindToSwallowsExceptions/
Expected behavior
The exception should not be swallowed. Dispatcher.CurrentDispatcher.UnhandledException
should fire.
Screenshots 🖼️
No response
IDE
Visual Studio 2022
Operating system
Windows 11 24H2
Version
ReactiveUI.WPF: net8.0-windows10.0.19041
Device
PC
ReactiveUI Version
20.2.45
Additional information ℹ️
No response