Xamarin Forms Entry 自定义控件不起作用

Xamarin Froms Entry Custom Control does not work

我正在尝试制作自定义控件以在多个地方使用它。 事情是它与标签一起工作正常但是当涉及到输入时它甚至不会 运行 它给了我

No property, BindableProperty, or event found for "EntryText"

这是我的自定义控件 Xaml:

    <ContentView.Content>
        <StackLayout>
            <Label x:Name="MyLabel" />
            <Entry x:Name="MyEntry" />
        </StackLayout>
    </ContentView.Content>
</ContentView>

及其背后的代码

   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();
        }
    }

及其用法

<StackLayout>
        <local:MyCustomControl 
            LabelText="{Binding BindingLabel}" 
            EntryText="{Binding BindingEntry}"/>
    </StackLayout>

注意: 我试图删除

 </ContentView.Content>

来自我的 xaml 因为我见过这样的例子, 而且我还尝试在构造函数

后面的代码中设置绑定
 public MyCustomControl()
        {
            InitializeComponent();
            MyEntry.SetBinding(Entry.TextProperty, new Binding(nameof(EntryText) , source: this));
        }

但条目都不起作用。 那么我该如何解决这个问题,如果我想将值绑定到视图模型,它是否会进行任何其他设置。 提前致谢。

更新: @Jessie Zhang -MSFT 谢谢你的帮助,我真的很感激, 但是我在 MyCustomControl 代码中发现了一个错误 => EntryText属性 是我必须声明 defaultBindingMode 才能将数据传递给 ViewModel 属性。 所以我将 Bindable属性 代码更改为:

public static  BindableProperty EntryTextProperty = BindableProperty.Create(
            nameof(EntryText),
            typeof(string),
            typeof(MyCustomControl),
            defaultBindingMode: BindingMode.OneWayToSource,
            propertyChanged:EntryBindablePropertyChanged
            );

您没有在 MyCustomControl.xaml 中绑定 Entry.TextEntryText 属性:

请参考以下代码:

<?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>

并且我用下面的代码做了测试,可以正常使用。

        <local:MyCustomControl 
        LabelText="test1" 
        EntryText="test2"/>

更新:

从文献Create a property,我们知道:

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.

因此,您可以将代码 EntryBindableProperty 更改为 EntryTextProperty,如下所示:

    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);
        }

    }

而 xaml 代码是:

<?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>