Xamarin BindableProperty 仅在我不使用 BindingContext 时才使用绑定

Xamarin BindableProperty works with binding only when I don't use BindingContext

在 Xamarin Forms 中,我创建了一个包含自定义组件的页面,我想像这样提供一个值:

<c:CustomComponent Test="{Binding Test}" />

但是,这不起作用。当我使用原始数字而不是 Binding 时,它会起作用。我发现的问题是,我的自定义组件使用了 ViewModel / BindingContext。因此,当我删除将我的 ViewModel 分配给 BindingContext 的行时,绑定有效。

为什么会这样,我如何在我的自定义组件中同时使用 BindingContext 和 BindableProperty?还是我必须在后面的代码中完成所有操作?

为了参考我如何创建 BindableProperty 的一些代码示例

public static readonly BindableProperty TestProperty = BindableProperty.Create(nameof(Test), typeof(int),
    typeof(CustomComponent), propertyChanged: (bindable, oldVal, newVal) => {
        Debug.WriteLine("TEST " + newVal);
    });

public int Test {
    get => (int)GetValue(TestProperty);
    set => SetValue(TestProperty, value);
}

"my custom component used a ViewModel / BindingContext."

创建可重用的自定义组件会更容易,如果它是“self-contained”- 没有 BindingContext。

构造函数:

public CustomComponent()
{
    InitializeComponent();
}

将组件视图模型中当前拥有的所有内容移动到 xaml.cs 代码隐藏文件中。

现在CustomComponent.xaml,给它起个名字(这里theComponent):

<ContentView ...
 x:Name="theComponent"
 x:Class=...>

当组件的 xaml 想要绑定到 属性 本身时,这会派上用场:

<Label Text="{Binding TestString, Source={x:Reference theComponent}}" />
public string TestString
{
    get => _testString;
    set {
        _testString = value;
        OnPropertyChanged();
    }
}
private string _testString = "test";

tl;dr: 如果组件在其 xaml 中有一个 x:Name="theComponent",可以使用 {Binding ..., Source={x:Reference theComponent}} 来引用它自己的属性.不需要 BindingContext。


如果您希望组件具有关联的 ViewModel,则使用上述技术您不必将 BindingContext 设置为该 VM。这样做:

public class MyViewModel
{
    public string TestString
    {
        get => _testString;
        set {
            _testString = value;
            OnPropertyChanged();
        }
    }
    private string _testString = "test";
}

自定义组件:

public MyViewModel VM { get; private set; }
public CustomComponent()
{
    InitializeComponent();
    VM = new MyViewModel();
}

在xaml中的用法:

<Label Text="{Binding VM.TestString, Source={x:Reference theComponent}}" />