使用数据绑定设置一个简单的组件
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
以上代码可以在ItemComponent
class中找到。此组件在 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 设置为当前项目,无需通过可绑定的 属性.
传递它
希望对您有所帮助!
我正在尝试设置一个具有数据绑定的组件。这基本上是一个单独的内容视图,具有类型为 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
class中找到。此组件在 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 设置为当前项目,无需通过可绑定的 属性.
希望对您有所帮助!