2
votes

There's a good chance I haven't had enough coffee today, but I've got an issue I've been going around in circles with for the last few hours.

I've created a CustomEntry class which is just a ContentView containing an Entry and a few other bits and I have added a new BindableProperty to this class which should set it's "Test" property.

The plan is to pass a string value from my ViewModel via this bindableproperty but rather than just hardcode the value (eg. ) I want to pass a value from my ViewModel using a binding (eg. Test="{Binding AStringFromMyViewModel}") - For some reason, when I try using a binding, the bindableproperty is never set.

Note that if I do hard-code the value, eg Test="123", then it works fine but doesn't work if I do Test="{Binding AStringFromMyViewModel}" as I have done below.

Here's what I have:

Page XML

<?xml version="1.0" encoding="UTF-8"?>
<pages:BasePage xmlns:pages="clr-namespace:ShoppingListNEW.Pages" NavigationPage.HasNavigationBar="True" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:helpers="clr-namespace:ShoppingListNEW.MarkupExtensions" xmlns:views="clr-namespace:ShoppingListNEW.Views" xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView" x:Class="ShoppingListNEW.Pages.SignUp">
    <StackLayout>
        <Label Margin="15,15,0,0" TextColor="#2b2c2e" Text="{helpers:TranslateExtension FirstName}"></Label>
        <views:CustomEntry Test="{Binding AStringFromMyViewModel, Mode=TwoWay}" BorderColor="Gray" HeightRequest="50" PlaceholderColor="Gray" Margin="15,0,15,0" BackgroundColor="Transparent" Text="{Binding FirstName}" TextColor="#232324" Placeholder="{helpers:TranslateExtension PleaseEnterYourFirstName}" AutomationId="txtFirstName" />
    </StackLayout>
</pages:BasePage>

Page Backing

public partial class SignUp : BasePage
{
    public SignUp()
    {
        InitializeComponent();

        //Bind our UI to our ViewModel
        BindingContext = App.Locator.SignUpViewModel;
    }
}

View Model

public class SignUpViewModel : ViewModelBase
{
    //I expect this value of "123" to be passed to my BindableProperty but it's not
    public string AStringFromMyViewModel {get; set; } = "123";

    public SignUpViewModel()
    {
    }
}

And finally my new CustomEntry control - I don't think you need the XML, as it's just the BindableProperty that isn't working.

public partial class CustomEntry : ContentView, INotifyPropertyChanged
{
    public static readonly BindableProperty TestProperty =
        BindableProperty.Create("Test", typeof(string), typeof(CustomEntry), null, BindingMode.OneWay, null);

    public string Test
    {
        get
        {
            return (string)GetValue(TestProperty);
        }
        set
        {
    //This is never called
            SetValue(TestProperty, value);
        }
    }

    public CustomEntry()
    {
        InitializeComponent();
        BindingContext = this;
    }

}

Thanks in advance.

2
why the bindable property BindingMode is set to OneWay but then in the xaml you are saying it's Mode=TwoWay? it might be causing issues, other than that i couldn't detect any errors on your code, have a pause of 15 and drink a cup of coffee :)Ricardo Dias Morais
Thanks, in all honesty it's only like that because I've been messing around with them so much trying to get it working! I think I may have found the solution now actually, will post it shortly.Martin Crawley

2 Answers

1
votes

As always, I manage to fix it 5 minutes after I post.

It looks like the issue was because of the BindingContext in the CustomEntry. Removing that kicks everything into life, so that's my next step!

0
votes

Modify your ViewModel to implement INotifyPropertyChanged and change your AStringFromMyViewModel {get; set; } become

private string _aString;
public string AStringFromMyViewModel {
    get => _aString;
    set {
        _aString = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AStringFromMyViewModel)))
    }
}