iamsophia
iamsophia

Reputation: 796

Binding issue on properties with get; vs with get; set; in Xamarin.Android

I have a XF app. In my ViewModel I have the following:

public ICommand ActBtnCmd { get; }
public ICommand AdpBtnCmd { get; }

public SettingsTabViewModel(SettingsTabPage settingsTabPage)
{
   ActBtnCmd = new Command<Templates.Button>((btn) => MessagingCenter.Send(this, "ActBtn", btn));
   AdpBtnCmd = new Command<Templates.Button>((btn) => MessagingCenter.Send(this, "AdpBtn", btn));
}

And in my XAML:

<t:Button Text="{Binding ActBtnText}" 
          TapCommand="{Binding ActBtnCmd}" 
          WidthRequest="30" 
          Theme="{Binding Theme}" />

Debugging in iOS is no problem. But when I debug the app in Android I get these messages in Application Output window:

Binding: 'ActBtnCmd' property not found on 'xxx.SettingsTabViewModel', target property: 'xxx.Templates.Button.TapCommand'
Binding: 'AdpBtnCmd' property not found on 'xxx.SettingsTabViewModel', target property: 'xxx.Templates.Button.TapCommand'

But when I changed my property like below then the messages are gone:

public ICommand ActBtnCmd { get; set; }
public ICommand AdpBtnCmd { get; set; }

Can anyone explain to me why am I getting these messages? And why am I only getting it in Android?

Upvotes: 2

Views: 1122

Answers (2)

Nkosi
Nkosi

Reputation: 247433

It is possible that this has to do with the Binding Mode of the bindable property being bind to.

The default binding mode for most properties is OneWay. When these properties are data-binding targets, then the target property is set from the source. Which only needs a get; from the property.

If how ever the binding mode is TwoWay then the source property will need both a get; and set;. This means that when the a property is a data-binding target, then the target is set from the source (as usual) but the source is also set from the target.

But if the source property is readonly (as in get; only) then you may see that message as the binder is unable to ensure that it can write back to the source.

To test this theory I would suggest Overriding the Binding Mode

If the default binding mode on the target property is not suitable for a particular data binding, it's possible to override it by setting the Mode property of Binding (or the Mode property of the Binding markup extension) to one of the members of the BindingMode enumeration.

<t:Button Text="{Binding ActBtnText}" 
    TapCommand="{Binding ActBtnCmd Mode=OneWay}" <!-- Note the Mode used -->
    WidthRequest="30" 
    Theme="{Binding Theme}" />

By setting the Mode to OneWay it should let the parser know not to expect a set; on the property and remove the warning.

As for why the run-time experience is different on the platforms, it could be that different XAML parsers are used for the platforms, where one uses a different default binding mode or ignores that warning message.

Reference Xamarin.Forms Binding Mode

Upvotes: 5

Monofuse
Monofuse

Reputation: 827

Get; can only be set using the constructor. Change it to :

{ get; private set; }

This way only the get is publicly available, but still modifiable by the class's methods.

Upvotes: 0

Related Questions