I'm trying to make a custom control to use it in multiple places. the thing is it works fine with the label but when it comes to entry it won't even run and it gives me
No property, BindableProperty, or event found for "EntryText"
here is my custom control Xaml:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
<ContentView.Content>
<StackLayout>
<Label x:Name="MyLabel" />
<Entry x:Name="MyEntry" />
</StackLayout>
</ContentView.Content>
</ContentView>
and its code behind
public partial class MyCustomControl : ContentView
{
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create(
nameof(LabelText),
typeof(string),
typeof(MyCustomControl),
propertyChanged: LabelTextPropertyChanged);
private static void LabelTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (MyCustomControl)bindable;
control.MyLabel.Text = newValue?.ToString();
Debug.WriteLine("LabelTextPropertyChanged: " control.MyEntry);
Debug.WriteLine("LabelTextPropertyChanged: new value" newValue);
}
public string LabelText
{
get => base.GetValue(LabelTextProperty)?.ToString();
set
{
base.SetValue(LabelTextProperty, value);
}
}
public static BindableProperty EntryBindableProperty = BindableProperty.Create(
nameof(EntryText),
typeof(string),
typeof(MyCustomControl),
propertyChanged:EntryBindablePropertyChanged
);
private static void EntryBindablePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (MyCustomControl)bindable;
Debug.WriteLine("EntryBindablePropertyChanged: " control.MyEntry);
Debug.WriteLine("EntryBindablePropertyChanged: new value" newValue);
}
public string EntryText
{
get => base.GetValue(EntryBindableProperty)?.ToString();
set
{
base.SetValue(EntryBindableProperty, value);
}
}
public MyCustomControl()
{
InitializeComponent();
}
}
and its Usage
<StackLayout>
<local:MyCustomControl
LabelText="{Binding BindingLabel}"
EntryText="{Binding BindingEntry}"/>
</StackLayout>
NOTE: I tried to remove the
</ContentView.Content>
from my xaml because i've seen some example like that, and also i've tried to set binding in the code behind constructor
public MyCustomControl()
{
InitializeComponent();
MyEntry.SetBinding(Entry.TextProperty, new Binding(nameof(EntryText) , source: this));
}
but neither did work for the entry . so how can i resolve this and does it make any additional setting if i want to bind the value to a view model. thanks in advance.
Update: @Jessie Zhang -MSFT thanks for your help I really appreciate it, however I discovered a bug in MyCustomControl code => EntryTextProperty is that i have to declare the defaultBindingMode to be able to get the data passed to a ViewModel Property. so i changed the BindableProperty code to:
public static BindableProperty EntryTextProperty = BindableProperty.Create(
nameof(EntryText),
typeof(string),
typeof(MyCustomControl),
defaultBindingMode: BindingMode.OneWayToSource,
propertyChanged:EntryBindablePropertyChanged
);
CodePudding user response:
You didn't bind the Entry.Text
and EntryText
property in MyCustomControl.xaml
:
Please refer the following code:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CardViewDemo.Controls.MyCustomControl"
x:Name="this"
>
<ContentView.Content>
<StackLayout BindingContext="{x:Reference this}">
<Label x:Name="MyLabel" Text="{Binding LabelText}" />
<Entry x:Name="MyEntry" Text="{ Binding EntryText}" />
</StackLayout>
</ContentView.Content>
</ContentView>
And I used the following code to did a test, it works properly.
<local:MyCustomControl
LabelText="test1"
EntryText="test2"/>
Update:
From document Create a property,we know that:
The naming convention for bindable properties is that the bindable property identifier must match the property name specified in the Create method, with "Property" appended to it.
So, you can change your code EntryBindableProperty
to EntryTextProperty
, just as follows:
public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(nameof(EntryText), typeof(string),typeof(MyCustomControl),string.Empty, BindingMode.TwoWay, null, EntryBindablePropertyChanged);
public string EntryText
{
get => base.GetValue(EntryTextProperty)?.ToString();
set
{
base.SetValue(EntryTextProperty, value);
}
}
And the xaml code is:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CardViewDemo.Controls.MyCustomControl"
x:Name="template"
>
<ContentView.Content>
<StackLayout >
<Label x:Name="MyLabel" Text="{Binding Source={x:Reference template},Path=LabelText}"/>
<Entry x:Name="MyEntry" Text="{Binding EntryText, Source={x:Reference template}}" >
</Entry>
</StackLayout>
</ContentView.Content>
</ContentView>