Skip to content

[Bug]: BindTo sometimes swallows exceptions #4003

Open
@timothylcooke

Description

@timothylcooke

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:

  1. Create a View that has a two-way binding to some property, called MyProperty.
  2. Create a ViewModel that has a read-only property called MyProperty (i.e. private setter).
  3. Set the View's DataContext to some object that does not have a property called MyProperty (e.g. myView.DataContext = new object()).
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions