Xamarin.forms 设置具有数据绑定的简单组件

Xamarin.forms 设置具有数据绑定的简单组件,xamarin.forms,xamarin-binding,xamarin-component,Xamarin.forms,Xamarin Binding,Xamarin Component,我正在尝试设置具有数据绑定的组件。这基本上是一个独立的内容视图,具有类型为Item的属性Item,并支持绑定。以下是绑定的定义: public static readonly BindableProperty ItemProperty = BindableProperty.Create( nameof(Item), typeof(Item), typeof(ItemComponent), null, defaultBindi

我正在尝试设置具有数据绑定的组件。这基本上是一个独立的内容视图,具有类型为
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
    }
}
这件物品似乎没有装订好。注释行有一个断点,没有中断。完整的源代码如下:

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

更新

仅解释我试图模拟的内容以及原因:

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

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


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

所以在看了你的例子之后,它变成了一个有点复杂的问题。因此,如果我的解释不清楚,请让我知道

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

MainPage.xaml(第14行):

第一部分告诉它绑定到
Demo
属性,它通常在其绑定上下文中查找该属性。但是,在第二部分中,您覆盖了它的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设置为当前项,无需通过bindable属性传递它


希望这能有所帮助!

谢谢!简单地注释一下设置
vm
的两行代码就有助于达到断点,从而证明你的观点。然而,你可能的解决方案看起来像是一个黑客。了解这个问题,我现在正在尝试一些更干净的解决方案,这取决于你想要什么,但这超出了这个问题的范围o、 您似乎希望将ViewModel作为
ItemComponent
的BindingContext。因为在一个对象上不能有两个BindingContext,所以只能引用另一个BindingContext。如果您离开ViewModel(不要认为我会将一个用于组件)还有很多其他的选择。我可能要做的就是为我想在 ITEMtase<代码>中显示的所有数据绑定属性,并从代码后面填充它们。考虑到它实际上可能有一种方式不引用另一个绑定上下文并保留视图模型。但是我认为这是一个不太干净的解决方案。n然后是
x:Reference
。您将
ItemComponent
拆分为两部分。外部组件:1在其视图中仅包含内部组件。2具有可绑定的
Item
属性,并且在其背后的代码中将Item属性同步到内部组件的BindingContext。因此,我关于引用的声明是只有这样才能保持VIEW模型是错误的,不要认为它是一个更好的选择,你为什么要说一个组件不需要一个VIEW模型?逻辑上,我看不出为什么一个页面可能只有一个组件不需要的区别。ngs。到目前为止,这似乎对我来说仍然是一种实用的方法。我也想到了组件的想法。但是,是的,它不仅不会干净,还会有一个额外的不需要的组件。我目前正在考虑一些选项来调整绑定,以便将它映射到VM的属性
public ItemComponent()
{
    InitializeComponent();
    vm = new ItemComponentViewModel();
    BindingContext = vm; //this breaks the functionality
}
<?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>