使用数据绑定设置一个简单的组件

setting up a simple component with data binding

我正在尝试设置一个具有数据绑定的组件。这基本上是一个单独的内容视图,具有类型为 Item 的 属性 Item 并支持绑定。以下是绑定的定义:

public static readonly BindableProperty ItemProperty
    = BindableProperty.Create(
                nameof(Item), typeof(Item), typeof(ItemComponent), null,
                defaultBindingMode: BindingMode.TwoWay,
                propertyChanged: ItemPropertyChanged);
private readonly ItemComponentViewModel vm;

static void ItemPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
    var view = (ItemComponent)bindable;
    view.Item = (Item)newValue;
}

public Item Item
{
    get => (Item)GetValue(ItemProperty);
    set
    {
        SetValue(ItemProperty, value);
        if (vm != null) vm.Data = value; // break point here
    }
}

该项目似乎没有绑定。注释行有一个断点并且没有中断。完整的源代码在这里:https://github.com/neville-nazerane/xamarin-component-sample

以上代码可以在ItemComponentclass中找到。此组件在 MainPage class 中被调用。

更新

只是为了解释我要模拟的内容以及原因:

为什么我们在页面中使用MVVM?虽然我们通过直接使用后台代码可以获得更好的类型安全性和性能,但是当页面的逻辑变得更大时,使用视图模型处理它并拥有一个简单绑定到它的视图会变得更清晰。

为什么我们有组件?这样我们就可以重用我们打算与某些功能一起使用的 UI 。如果这个功能变得复杂,它可能需要一个视图模型,原因与上面解释的相同。因此,如果页面需要视图模型,我不明白为什么组件在某些时候也不需要它们。

考虑到这一点,这确实感觉像是一个不容易找到示例的粒子要求。

因此,在查看您的示例后,发现这是一个有点复杂的问题。所以如果我的解释不清楚,请告诉我。

基本上问题出在这两个代码段上:

MainPage.xaml(第 14 行):

<local:ItemComponent Item="{Binding Demo}" />

ItemComponent.xaml.cs(第 43 行):

public ItemComponent()
{
    InitializeComponent();
    vm = new ItemComponentViewModel();
    BindingContext = vm; //this breaks the functionality
}

您告诉它绑定到 Demo 属性 的第一部分,它会像往常一样在它的 BindingContext 中查找此 属性。但是,在第二部分中,您覆盖了它的 BindigContext 并将其设置为 ItemComponentViewModel 此 ViewModel 但是没有 属性 Demo 因此 {Binding Demo} 在这个新的 BindingContext 上不起作用你设置好了。

现在,您的演示应用程序的一个可能解决方案是将 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:SampleApp"
             x:Class="SampleApp.MainPage"
             x:DataType="local:MainViewModel"
             x:Name="MyDemoPage">
    <StackLayout>
        <Label Text="Manual:" />
        <Label Text="{Binding Demo.Title}" />
        <Label Text="Component: " />
        <local:ItemComponent Item="{Binding Path=BindingContext.Demo, Source={x:Reference MyDemoPage}}" />
    </StackLayout>
</ContentPage>

基本上,我们现在将 Demo 绑定放置在 ItemComponent 控件的 BindingContext 之外。但是,如果您想在 ListView 中使用它(如果我从您的原始问题中没记错的话,此解决方案可能不起作用,并且您可能必须删除 ItemComponentViewModel 并直接绑定到属性(ListView 已经确保 ItemComponent 的 BindingContext 设置为当前项目,无需通过可绑定的 属性.

传递它

希望对您有所帮助!