Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Binding Conversion Failures #3094

Open
WalkerCodeRanger opened this issue Dec 7, 2021 · 1 comment
Open

Expose Binding Conversion Failures #3094

WalkerCodeRanger opened this issue Dec 7, 2021 · 1 comment

Comments

@WalkerCodeRanger
Copy link
Contributor

Is your feature request related to a problem? Please describe.

Yes. If a user enters a value in a control that cannot be converted to the view model property type, the conversion fails but there is no way to notify the user of this. The problem is that validation happens on the view model that isn't updated in this case. Furthermore, there is no way to detect that a binding conversion failure has happened. So there isn't any way for us to wire that failure up to some indicator to the user. Effectively, this should be shown to the user as if it were a validation error, but there is no way to do that.

As an example, if a textbox is bound to a property of type int and the user enters "32a" then the conversion to int will fail but there is no way to indicate to the user that the value "32a" is bad.

Describe the solution you'd like

Add one or more properties to the IReactiveBinding<out TView, out TValue> interface to expose when a binding conversion fails. This would be similar to the ThrownExceptions property on ReactiveCommand and other types. However, in this case, I don't think it can simply be an IObservable<Exception>. It might also be a good idea to change the IBindingTypeConverter interface to provide a reason for the failure when the conversion fails. That would enable better handling of these failures (e.g. by giving specific reasons for the failure to the user).

Describe alternatives you've considered

If we use WPF binding declared in the XAML, then it will mark fields errored when the conversion fails. However, we like the strongly typed binding and other features provided by ReactiveUI binding expressions. Also, developers on other platforms may not have this option.

With ReactiveUI based binding, there don't appear to be any other alternatives. The PropertyBinderImplementation class sets up the conversions for binding. It calls the conversion and does nothing if the conversion fails. There doesn't appear to be any workaround to detect the conversion failure.

Describe suggestions on how to achieve the feature

I am mostly concerned about conversion from the view to the view model, but conversion from the view model to the view should probably also be exposed. There are three ways in which a binding conversion could fail:

  1. The IBindingTypeConverter.TryConvert method could return false.
  2. The IBindingTypeConverter.TryConvert could throw an exception (I believe this is not the intended semantics of the interface, but it can't be ruled out).
  3. The converter override function parameter to Bind could throw an exception.

To fully represent this, I think there would need to be some kind of BindingConversionFailure class with properties for the value being converted, the type being converted to, the conversion hint, the IBindingTypeConverter used, the direction of conversion (either view to view model or vice versa, this is something different than the current BindingDirection enum) and the exception (null if TryConvert returned false). The IReactiveBinding interface could then have a property of type IObservable<BindingConversionFailure> that provided each conversion failure.

One issue with this is that when the IBindingTypeConverter.TryConvert method returns false, no reason is given for the conversion failure. That could make it difficult to indicate to the user what the problem is. Perhaps the IBindingTypeConverter interface should be changed in some way to provide a reason the conversion failed and this could be included in the BindingConversionFailure class I propose. Alternatively, the IBindingTypeConverter interface could be changed to have a Convert method that always throws an exception on failure. The exception type and message would then provide a way to determine why the conversion failed and make the BindingConversionFailure class more consistent because it would then always have an exception.

Alternatively, the failure of the two directions of conversion (view to view model and vice versa) could be split into separate observables. It might be very common to only care about one direction (e.g. conversion from view is much more likely to fail and should be shown to the user). Having separate observables would make that easier and could simplify the BindingConversionFailure class by removing the need for an indication of the direction.

Additional context

To me, this seems like it should be part of a larger extension to ReactiveUI.Validation that makes it easy to treat binding conversion failures as validation errors. However, for anything like that to be possible the failures must first be exposed. Nevertheless, it might make sense to design this in conjunction with changes to ReactiveUI.Validation to make sure any requirements needed by it are satisfied.

@glennawatson
Copy link
Contributor

We would be open to a PR with this suggestion. Tricks would be changing the pipeline to pass back some sort of context in the binding failure areas I'm guessing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants