Xamarin Forms绑定到对象属性

5
我在Xamarin Forms项目中似乎遇到了数据绑定问题。我有两个视图:一个用于列出项目,另一个用于查看详情。
列表视图可以很好地加载项目列表及其所有属性,但详细页面是空白的,无法绑定属性。
列表的视图模型大致如下:
public class MainPageViewModel : ViewModelBase
{
    public MainPageViewModel(IItemService itemService) : base(itemService) { }

    public ObservableCollection<ItemModel> Items { get; set; } = new ObservableCollection<ItemModel>();

    public async override void Start()
    {
        base.Start();

        Items.Clear();

        var results = await service.GetItems();
        foreach (var result in results)
        {
            Items.Add(result);
        }

        IsLoading = false;
    }
}

这段代码与以下的XAML绑定:

<ListView x:Name="ItemListView" ItemsSource="{Binding Items}" ItemSelected="ItemListView_ItemSelected">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <StackLayout Orientation="Vertical">
                        <Image Source="{Binding Image}" />
                    </StackLayout>
                    <StackLayout Orientation="Vertical" Grid.Column="1">
                        <Label Text="{Binding Name}" />
                        <Label Text="{Binding Description}" />
                    </StackLayout>
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

再次测试成功了。 但是详细视图看起来像这样:
public class DetailsPageViewModel : ViewModelBase
{
    public DetailsPageViewModel(IItemService itemService) : base(itemService) { }

    private ItemModel item;
    public ItemModel Item
    {
        get { return item; }
        set
        {
            item = value;
            RaisePropertyChanged();
        }
    }

    protected string ItemId { get; set; }

    public void Init(string itemId)
    {
        this.ItemId = itemId;
    }

    public async override void Start()
    {
        base.Start();

        Item = await service.GetItem(ItemId);

        IsLoading = false;
    }
}

我正在尝试将ItemModel属性绑定到详细视图上的标签:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MvvmCrossFormsDemo.Views.DetailsPageView">
    <StackLayout>
    <Label Text="{Binding Item.Name}" />
    <Image Source="{Binding Item.Image}" />
    </StackLayout>
</ContentPage>

页面完全空白。我需要在ItemModel中添加INotifyPropertyChanged吗?如果是,我不明白为什么,因为ListView在没有任何这样的需求的情况下绑定了相同的模型,那么为什么普通标签不能绑定呢?我做错了什么?
1个回答

9

首先,您需要在ViewModel中指定属性。ListView已经直接绑定到ViewModel中的属性,然后ViewCell已经绑定到单个项目。

在详细页面中,您直接绑定到ViewModel,因此没有Name或Image属性,它们是Item的属性,您需要先指定它们。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MvvmCrossFormsDemo.Views.DetailsPageView">
    <StackLayout>
        <Label Text="{Binding Item.Name}" />
        <Image Source="{Binding Item.Image}" />
    </StackLayout>
</ContentPage>

啊,我试过了,但忘记更新我的代码。我确实绑定到Item.Name和Item.Image(不是ItemModel,因为Item是属性的名称,ItemModel是类型),但它仍然不起作用。我已经更新了原始问题,并添加了这个片段以显示我正在绑定到详细项属性,但感谢您指出这一点! - SelAromDotNet
你能否在 Item 集合上设置断点,并确保它被正确设置了吗?其次,你确定该页面的 BindingContext 被正确设置了吗? - Adam
好的,是的,谢谢。这里变得有趣了:我在get和set上设置了断点,get被调用了(因为bindingcontext肯定被设置了),但在调用Start之前它是null的。在调用Start时,set属性被调用,并且Item属性被更新为结果。RaisePropertyChanged被调用,但GET再也没有被调用!也许这个RaisePropertyChanged中有一个bug? - SelAromDotNet
1
啊哈!显然是有问题的!我正在使用MvvmCross的基本MvxViewModel,它有自己的INofifyPropertyChanged实现。当我将其剥离并放入自己的简单实现时,它就可以工作了!所以看起来要么是MvvmCross中存在一个错误,要么是我在使用它时出了问题。我会将您的答案标记为正确的,进行一些挖掘,并在我能够确定问题的情况下发布一个新问题。谢谢! - SelAromDotNet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接