Bug 44213 - Can't bind to specific properties through OnPlatform
Summary: Can't bind to specific properties through OnPlatform
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms (show other bugs)
Version: 2.3.2
Hardware: PC Windows
: --- enhancement
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2016-09-12 18:46 UTC by Clint
Modified: 2017-12-28 15:08 UTC (History)
7 users (show)

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


Description Clint 2016-09-12 18:46:18 UTC
It would be great if we could do OnPlatform binding to specific properties of a control.
It would at least give a way to band-aid this other bug:

Let's say you have an ```Entry```, and you want to bind the ```HeightRequest``` with platform-specific values which themselves are bindings.

So not this kind of simple hard-coded values:
                      <OnPlatform x:TypeArguments="x:Double">

but something dynamic more like this:
                            <OnPlatform x:TypeArguments="x:Double">
                                    <Binding Converter="{StaticResource TimesxConverter}"
                                             Source="{x:Reference MyEntryControl}" />
What this would do is take the ```FontSize``` of the ```MyEntryControl```, run it through a converter to get a value * 1.25, then use that result as the ```HeightRequest```.
Problem: This throws a run-time exception of TypeMismatch between ```Binding``` and ```System.Double```.  In other words it doesn't seem to accept that the binding can return a double.

The converter and binding works if not use with OnPlatform:
                                <Entry x:Name="MyEntryControl"
                                       HeightRequest="{Binding Path=FontSize,
                                                               Source={x:Reference MyEntryControl},
                                                               Converter={StaticResource TimesxConverter},
                                       Text="{Binding StockNumber}"
                                       Style="{StaticResource EntryStyleLrg}" />
Comment 1 Rui Marinho 2016-10-04 18:25:19 UTC
Why dont you check on your converter or view model?
Something like

> if(Device.OS == TargetPlatform.iOS)
Comment 2 Rui Marinho 2016-10-04 18:31:18 UTC
This s a new feature request and will be added to our backlog. 

Comment 3 Clint 2016-10-04 18:34:52 UTC
Using a converter is a band-aid for the actual problem, which is that we can't bind properties directly within OnPlatform in XAML.

Additionally, if we can't supply a value from the XAML then the converter would have to be hard-coded and not be very reusable.  I might need a scale factor of 1.25 for one control and 2.50 on another. 

As for ViewModel - We're talking about the UI... ViewModel shouldn't know anything about UI; that would be a complete violation of MVVM design patterns. 

Thank you for adding it as a feature request
Comment 4 Stephane Delcroix 2017-01-24 13:17:13 UTC
the proposed XAML is invalid, as that would mean the OnPlatform object is the target of the binding to double.

but this makes sense to support:

<OnPlatform x:TypeArguments="BindingBase">
    <Binding Converter="{StaticResource TimesxConverter}"
             Source="{x:Reference MyEntryControl}" />

That'd mean the OnPlatform returns one Binding or the other depending on the platform.

I made the required change to support that in https://github.com/xamarin/Xamarin.Forms/pull/709
Comment 5 Clint 2017-01-24 13:26:34 UTC

That's wonderful.  Thank you!
Comment 6 Clint 2017-01-24 13:27:56 UTC
OH... Any guess when that might make its way to a stable update of Xamarin.Forms?  I don't get to use 'experimental' code at work.  If its not in the official update we don't put it in product code.
Comment 7 Samantha Houts [MSFT] 2017-02-01 18:12:25 UTC
Should be fixed in 2.3.5-pre1. Thank you!
Comment 9 Carlos Martínez 2017-10-03 07:18:19 UTC
I'm not able to do this.... I do not know if is the binding or the converter: 

Using Xamarin.forms

                                                Android="{Binding Reservation.MailEnviado, Converter={StaticResource BoolToImageConverter}}" />
                                        Command="{Binding ShowWaitingListCommand}">
                                            <renderers:TransparentSelectableEffect />
                                                iOS="{Binding Reservation.MailEnviado, Converter={StaticResource BoolToImageConverter}}" />
Comment 10 Mike Miller 2017-12-28 15:08:42 UTC
This throws an object reference error for me - Object not set to an instance of an object.

<ct:StyledPicker Grid.Column="1" Grid.Row="8"    
                            Style="{StaticResource FormPickerStyle}"
                            ItemsSource="{Binding TimeZones}" 
                            ItemDisplayBinding="{Binding DisplayName}"
                            SelectedItem="{Binding TimeZoneOffset}">
                            <OnPlatform x:TypeArguments="x:String" Android="{Binding Resources[adminPlaceholderTimeZone]}" iOS="{Binding Resources[adminPlaceholderTimeZone]}" Default="" />

This is just a control based on picker with some additional visual properties.  It works fine if the values are static or if I comment out the Picker.Title.  It won't build with what I have here.

Note You need to log in before you can comment on or make changes to this bug.