Bug 46603 - Converter not executed if binding value is null
Summary: Converter not executed if binding value is null
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: 2.3.3
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2016-11-08 18:17 UTC by Clint
Modified: 2017-04-05 16:34 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Clint 2016-11-08 18:17:25 UTC
The idea here is to have a converter that lets you make some element visible after a given value is greater than something.  For example, if the number of pages is greater than 1... or the number of Widgets is greater than 20...  Then some other element becomes visible.

Let's say you have this markup:

                               IsVisible="{Binding CurrentDocument.DocumentInfo.PageCount,
                                                   Converter={StaticResource ValueGreaterThanBoolConverter},

However, any of the items in the binding (CurrentDocument.DocumentInfo.PageCount) could be null.
One would expect that 'null' would be sent to the converter, and the converter would continue to do its evaluation.

    public class ValueGreaterThanBoolConverter : IValueConverter
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
                if (value == null || parameter == null) return false;
                return ((decimal) value > (decimal) parameter);
            catch (Exception ex)
                Debug.WriteLine($"GET Error {ex.Message}");
            return false;

However, this is not the case.  The converter is never executed.  The element this binding is using is therefore always visible.

At first I thought I could work around it by inverting the logic, looking for LessThan then using a BoolInvert converter... Until I realized I already had assigned the converter and thus couldn't assign a second one to invert the result.
Comment 1 Clint 2016-11-08 18:58:33 UTC
Second example.  This one evaluates a property to determine which of two icons should be visible; StatusIconConnected or StatusIconDisconnected

            <Image Grid.Row="0"
                   IsVisible="{Binding AppVM.IsMicrophoneAvailable}"
                   Source="{StaticResource StatusIconConnected}" />
            <Image Grid.Row="0"
                   IsVisible="{Binding AppVM.IsMicrophoneAvailable,
                                       Converter={StaticResource BoolInvertConverter}}"
                   Source="{StaticResource StatusIconDisConnected}" />

However, because the property .IsMicrohoneAvailable is not found on the AppVM, the converter is never executed and so BOTH icons are displayed; one on top of the other.  

Nobody would expect that.  If two icons are both evaluating off the same property and one is bool, and the other is boolInverted the normal thinking is that one of them has to evaluate to true and the other false: Just has to be, right?

Not in this case.  Both are true because the evaluation stops in its tracks when it can't find something, rather than passing along a null to the converter then allowing it to do its job.
Comment 2 Stephane Delcroix 2016-12-20 16:51:16 UTC
This is by design
Comment 3 Clint 2016-12-30 15:36:11 UTC
By design?  Really?  Its different than WPF design and that's going to confuse if not anger a LOT of existing developers.  Its also going to keep a lot of logic from WPF apps from smoothly migrating to Xamarin.

NULL is a perfectly valid value, it is something that should be sendable to a converter, and sendable as a CommandParameter

There is also a further propagation of the problem with this design, related to bug #51147

When binding a command to a UI element and specifying a CanExecute method..
The XAML is required to include a CommandParameter whether it will be used by the CanExecuteMethod or not.  EX:
   Command="{Binding ScoobyScanCommand}"
   CommandParameter="{Binding SelectedDocument.DisplayBarcode}"

If the CommandParameter is null, either because it just wasn't included in the XAML or because the binding evaluates to null then the evaluation isn't executed/honored.

Use case:
You want a button enabled when you have a object, and disabled when you don't.

When you set an object to a non-null value the Command CAN execute and the button enables.
When you set an object to null the command CANNOT execute and the button disables.

Actually happening:
When you set the object to a non-null value the button enables.
When you set the object to null the evaluation just doesn't take place, so the button remains enabled.
Comment 4 david 2017-01-03 02:45:53 UTC
FWIW I would prefer null to be passed on to a converter, rather than causing the converter to be bypassed. 

Replacing null with something sensible is one of the primary functions of a converter.
Comment 5 David Ortinau [MSFT] 2017-04-05 16:34:32 UTC
This is a design discussion, so let's please move forward on the existing Evolution thread.


This PR also appears to apply: