设置带有数据绑定的简单组件

时间:2019-03-03 07:00:16

标签: xamarin.forms xamarin-binding xamarin-component

我正在尝试设置具有数据绑定的组件。这基本上是一个单独的内容视图,该视图具有类型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

以上代码可在ItemComponent类中找到。该组件在MainPage类中被调用。

更新

仅说明我要模拟的内容以及原因:

为什么我们在页面中使用MVVM?虽然我们可以直接使用后面的代码来提供更好的类型安全性和性能,但是当页面的逻辑变得更大时,使用视图模型来处理它并拥有一个简单地绑定到视图的视图将变得更加干净。

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

这被认为确实像是粒子要求,但不容易找到示例。

1 个答案:

答案 0 :(得分:1)

因此,在看完您的示例后,事实证明这是一个复杂的问题。因此,如果我的解释不清楚,请告诉我。

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

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设置为当前Item,而无需通过可绑定的属性来传递它。

希望这会有所帮助!