0

我正在尝试使用数据绑定设置组件。这基本上是一个单独的内容视图,它具有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。如果这个功能变得复杂,它可能需要一个视图模型,原因与上面解释的相同。因此,如果页面需要视图模型,我不明白为什么组件在某些时候也不需要它们。

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

4

1 回答 1

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 并将其设置为ItemComponentViewModelthis 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的 BindingContext 之外。ItemComponent但是,如果您想在 ListView 中使用它(如果我从您的原始问题中没记错的话,此解决方案可能不起作用,您可能必须删除ItemComponentViewModel并直接绑定到属性(ListView 已经确保 BindingContext你ItemComponent的设置为当前项目,无需通过可绑定属性传递它。

希望这可以帮助!

于 2019-03-03T12:24:16.443 回答