locked
Bindable Property on Custom Control Error RRS feed

  • Question

  • User254531 posted

    Hi,

    I have a custom control for entry, and Binding for the text is not working. It works before this, and now it's not working anymore. I have no idea why it stopped working.

    EntryBinding.xaml

    <?xml version="1.0" encoding="UTF-8"?>
    <Grid xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="TestingApp.EntryBinding">
        <Entry Text="{Binding Path=MyText, Mode=TwoWay}"/>
    </Grid>
    

    In my EntryBinding I have a BindableProperty called MyText

    public static readonly BindableProperty MyTextProperty = BindableProperty.Create(
        "MyText",
        typeof(string),
        typeof(EntryBinding),
        "",
        propertyChanged: OnMyTextChanged);
    
    private static void OnMyTextChanged(BindableObject obj, object oldValue, object newValue)
    {
        var item = obj as EntryBinding;
        var newV = (string)newValue;
        var oldV = (string)oldValue;
    }
    
    public string MyText
    {
        get
        {
            return (string)GetValue(MyTextProperty);
        }
        set
        {
            SetValue(MyTextProperty, value);
        }
    }
    

    Then I tried to use the custom control in my MainPage like this: <local:EntryBinding MyText="{Binding TheText}"/>

    However, when I run, I receive this error: Binding: 'TheText' property not found on 'TestingApp.MainPage', target property: 'TestingApp.MYCB.MyText'

    Below is my MainPage and my Items class

    public partial class MainPage : ContentPage
    {
        Items items = new Items();
    
        public MainPage()
        {
            InitializeComponent();
    
            BindingContext = items;
        }
    
        void Handle_Clicked_2(object sender, System.EventArgs e)
        {
            items.TheText = "WOW";
        }
    }
    
    public class Items : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        string _TheText = "";
        public string TheText
        {
            get { return _TheText; }
            set
            {
                _TheText = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TheText"));
            }
        }
    }
    

    I don't know where went wrong. It run perfectly before this, and now it just have the error I mentioned above.

    Thanks in advance, AziziAziz

    Wednesday, April 10, 2019 4:54 AM

All replies

  • User48866 posted

    Could you try to configure the XAML compilation if you have not done before?

    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xamlc

    Edit Clean the solution before deploying it again.

    Wednesday, April 10, 2019 5:19 AM
  • User254531 posted

    @PrabakaranRamasamy Thank you so much for your time. However, the same error occurs even though I've added the XAML compilation. Any other ideas?

    Wednesday, April 10, 2019 6:21 AM
  • User382871 posted

    Could you post the code of page.xaml? I've reproduced the code and it works well. As the following shows page.xaml.cs ``` [XamlCompilation(XamlCompilationOptions.Compile)] public partial class Page4 : ContentPage { Items items = new Items { TheText = "TheText" }; public Page4() { InitializeComponent();

        BindingContext = items;
    }
    

    }

    public class Items : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

    string _TheText = "====";
    public string TheText
    {
        get { return _TheText; }
        set
        {
            _TheText = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TheText"));
        }
    }
    

    } page.xaml ```

    Wednesday, April 10, 2019 8:47 AM
  • User254531 posted

    Hi @yelinzh Thanks for your time.

    EntryBinding.xaml.cs

    public partial class EntryBinding : Grid
    {
        public EntryBinding()
        {
            InitializeComponent();
    
            BindingContext = this;
        }
    
        #region MyTextProperty
        public static readonly BindableProperty MyTextProperty = BindableProperty.Create(
            "MyText",
            typeof(string),
            typeof(EntryBinding),
            "",
            propertyChanged: OnMyTextChanged);
    
        private static void OnMyTextChanged(BindableObject obj, object oldValue, object newValue)
        {
            var item = obj as EntryBinding;
            var newV = (string)newValue;
            var oldV = (string)oldValue;
        }
    
        public string MyText 
        {
            get 
            {
                return (string)GetValue(MyTextProperty);
            }
            set
            {
                SetValue(MyTextProperty, value);
            }
        }
        #endregion
    }
    

    I realize if I remove ~~BindingContext = this~~ , then the error gone and everything works perfectly.

    However, I need to name my Entry to and in OnMyTextChanged method I need add item.entry.Text = item.MyText Is this the correct way of doing it?

    The other solution is to change my MainPage.xaml in the binding part like below:

    <?xml version="1.0" encoding="utf-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:TestingApp"
                 x:Name="this"
                 x:Class="TestingApp.MainPage">
        <StackLayout Padding="10">
            <local:EntryBinding MyText="{Binding Path=BindingContext.TheText, Mode=TwoWay, Source={x:Reference this}}"/>
        </StackLayout>
    </ContentPage>
    

    Which solution is better? Changing the EntryBinding.xaml.cs or changing my MainPage.xaml?

    Wednesday, April 10, 2019 8:52 AM
  • User254531 posted

    Hi @yelinzh

    It's working now. Below is my codes for MainPage and EntryBinding.

    MainPage.xaml

    <?xml version="1.0" encoding="utf-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:TestingApp"
                 x:Name="this"
                 x:Class="TestingApp.MainPage">
        <StackLayout Padding="10">
            <local:EntryBinding MyText="{Binding Path=BindingContext.TheText, Mode=TwoWay, Source={x:Reference this}}"/>
            <!--<local:EntryBinding MyText="{Binding TheText}"/>--> <!--This code does not work-->
        </StackLayout>
    </ContentPage>
    

    MainPage.xaml.cs

    public partial class MainPage : ContentPage
    {
        Items items = new Items();
    
        public MainPage()
        {
            InitializeComponent();
    
            BindingContext = items;
        }
    
        void Handle_Clicked(object sender, System.EventArgs e)
        {
            Console.WriteLine(items.TheText);
        }
    
        void Handle_Clicked_2(object sender, System.EventArgs e)
        {
            items.TheText = "WOW";
        }
    }
    
    public class Items : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        string _TheText = "";
        public string TheText
        {
            get { return _TheText; }
            set
            {
                _TheText = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TheText"));
            }
        }
    }
    

    EntryBinding.xaml

    <?xml version="1.0" encoding="UTF-8"?>
    <Grid xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="TestingApp.EntryBinding">
        <Entry Text="{Binding Path=MyText, Mode=TwoWay}"/>
    </Grid>
    

    EntryBinding.xaml.cs

    public partial class EntryBinding : Grid
    {
        public EntryBinding()
        {
            InitializeComponent();
    
            BindingContext = this;
        }
    
        #region MyTextProperty
        public static readonly BindableProperty MyTextProperty = BindableProperty.Create(
            "MyText",
            typeof(string),
            typeof(EntryBinding),
            "",
            propertyChanged: OnMyTextChanged);
    
        private static void OnMyTextChanged(BindableObject obj, object oldValue, object newValue)
        {
            var item = obj as EntryBinding;
            var newV = (string)newValue;
            var oldV = (string)oldValue;
        }
    
        public string MyText 
        {
            get 
            {
                return (string)GetValue(MyTextProperty);
            }
            set
            {
                SetValue(MyTextProperty, value);
            }
        }
        #endregion
    }
    

    Above code is a working code. However, I can't simply use {Binding TheText}, I must have the Path and Source for the binding. Let me know if this is a good way to solve this issue.

    Again, thank you so much for your time. Appreciate it.

    Wednesday, April 10, 2019 9:00 AM
  • User382871 posted

    @PrabakaranRamasamy How about using Assignment directly. ``` [XamlCompilation(XamlCompilationOptions.Compile)] public partial class Page4 : ContentPage { Items items = new Items { TheText = "ATheText" }; public Page4() { InitializeComponent();

        BindingContext = items;
        entry_.MyText = items.TheText;
    }
    

    }

    public class Items : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

    string _TheText = "====";
    public string TheText
    {
        get { return _TheText; }
        set
        {
            _TheText = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TheText"));
        }
    }
    

    } Or <strong>create another Entry and set IsEnabled to false</strong>. [XamlCompilation(XamlCompilationOptions.Compile)] public partial class Page4 : ContentPage { Items items = new Items { TheText = "ATheText" }; public Page4() { InitializeComponent();

        BindingContext = items;
        entry_.MyText = entry.Text;
    }
    

    }

    public class Items : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

    string _TheText = "====";
    public string TheText
    {
        get { return _TheText; }
        set
        {
            _TheText = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TheText"));
        }
    }
    

    }

    <Entry x:Name="entry" Text="{Binding TheText}"/>
    

    ```

    Wednesday, April 10, 2019 10:07 AM