自定义 Xamarin 表单控件的数据绑定失败,但适用于普通控件

Data binding fails for a custom Xamarin forms control but works for a normal one

我有一个简单的自定义控件,我在我的 Xamarin 表单应用程序的 ContentPage(实际上是一个 LoginPage)中使用它。自定义控件有一个名为 EntryText 的 属性,我试图将其绑定到 LoginViewModelEmail 属性.

如果我将 Email 与自定义控件的 EntryText 绑定,它似乎不起作用。但是,如果我将 Email 绑定到像 EntryText 这样的普通控件,它确实可以正常工作。我在这里做错了什么?

我的自定义控件:

public class FlakeEntry2 : StackLayout
{
    public Entry Entry;
    public Label ErrorLabel;

    public FlakeEntry2()
    {
        Entry = new Entry { };
        Children.Add(Entry);

        ErrorLabel = new Label
        {
            FontAttributes = FontAttributes.Italic,
            TextColor = Color.Red,
        };
        Children.Add(ErrorLabel);
    }

    #region Text property which I am trying to bind

    public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(
                                                   propertyName: nameof(EntryText),
                                                   returnType: typeof(string),
                                                   declaringType: typeof(FlakeEntry2),
                                                   defaultValue: null,
                                                   defaultBindingMode: BindingMode.TwoWay,
                                                   propertyChanged: EntryTextPropertyChanged);

    public string EntryText
    {
        get { return GetValue(EntryTextProperty)?.ToString(); }
        set { SetValue(EntryTextProperty, value); }
    }

    private static void EntryTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (FlakeEntry2)bindable;
        control.Entry.Text = newValue?.ToString();
    }

    #endregion
}

我尝试绑定的视图 (LoginPage) 如下所示:

<StackLayout Orientation="Vertical" Spacing="10">
    <custom:FlakeEntry2 x:Name="Email" EntryText="{Binding Email}" /> <!--This does not work-->
    <Entry Text="{Binding Email}"/> <!--This works-->
</StackLayout>

最后,ViewModel 几乎是标准的并且实现了 INotifyPropertyChangedEmail 属性 看起来像:

private string _email;
public string Email
{
    get { return _email; }
    set
    {
        _email = value;
        NotifyPropertyChanged();
    }
}

我尝试添加一个基于 XAML 的自定义控件(当前的控件仅基于 C#)。 我已尝试将 BindingContext={Binding} 显式添加到 LoginPage 中使用的自定义控件。 我已经阅读了很多博客,但无济于事。有人可以指出我正确的方向吗?

我听说 WPF 和 XF 绑定甚至 XAML 语法之间有些不同,但我对 WPF 知之甚少。

随便。

如何使用级联绑定并控制您的组件,避免暴露其内部视图?

我一直使用这种方法并且对我来说效果很好,看看它是否也适合你:

public class FlakeEntry2 : StackLayout
{
    private Entry Entry;
    private Label ErrorLabel;

    public FlakeEntry2()
    {
        Entry = new Entry { };

        ErrorLabel = new Label
        {
            FontAttributes = FontAttributes.Italic,
            TextColor = Color.Red,
        };

        this.Entry.SetBinding(Entry.TextProperty, new Binding(nameof(EntryText), source: this));
        // You'll need to do the same to label's and other properties you need expose, but you get rid of the 'OnChanged' methods

        Children.Add(Entry);
        Children.Add(ErrorLabel);
    }

    #region Text property which I am trying to bind

    public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(
                                                   propertyName: nameof(EntryText),
                                                   returnType: typeof(string),
                                                   declaringType: typeof(FlakeEntry2),
                                                   defaultValue: null,
                                                   defaultBindingMode: BindingMode.TwoWay);
    public string EntryText
    {
        get { return GetValue(EntryTextProperty)?.ToString(); }
        set { SetValue(EntryTextProperty, value); }
    }

    #endregion
}

您的 XAML 和 VM 上的任何内容都不应更改。