You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ObservableCollection双向绑定问题:第二页ListView显示空白

问题描述

我的项目包含3个页面、2个ViewModel和2个模型。第一页可正常将未结订单填充至ListView,但点击第一页ListView项触发Orders_ItemTapped事件后,本该将对应订单条目填充到第二页的ListView中,却出现ListView空白的情况。

调试过程中无报错,点击事件能调用所有方法但无效。经初步排查,问题可能源于双向数据绑定、ViewModel的使用方式或点击事件中ViewModel的实例化逻辑。

为进一步测试,我在第二个ViewModel的构造函数中硬编码调用GetOrderItemsById()来填充列表,此时第二页可正常显示所有订单条目。我不熟悉依赖注入,推测问题与ViewModel中ObservableCollection的属性/构造函数使用或点击事件中ViewModel的实例化有关。


相关代码

页面1 "OpenOrdersPage" 代码后台

using ApexHQ_Mobile.Models;
using ApexHQ_Mobile.ViewModels;
namespace ApexHQ_Mobile.Pages;

public partial class OpenOrdersPage : ContentPage
{
    private OpenWOrdersVM vm;
    public OpenOrdersPage()
    {
        InitializeComponent();
        vm = new OpenWOrdersVM();
        this.BindingContext = this.vm;
    }

    private  void Orders_ItemTapped(object sender, ItemTappedEventArgs e)
    {
        try
        {
            var order = (WarehouseOrder)e.Item;
            var vm = new WOrderItemsVM { OrderId = order.Id };
            vm.GetOrderItems();
            var itemsPage = new WOrderItemsPage();
            itemsPage.BindingContext = vm;
            Shell.Current.GoToAsync(nameof(itemsPage));
        }
        catch (Exception ex)
        {
             DisplayAlert("Error", ex.Message, "OK");
            throw;
        }
    }
}

页面2 "WOrderItemsPage" 代码后台

using ApexHQ_Mobile.ViewModels;
namespace ApexHQ_Mobile.Pages;

public partial class WOrderItemsPage : ContentPage
{
    private WOrderItemsVM vm;
    public WOrderItemsPage()
    {
        InitializeComponent();
        vm = new WOrderItemsVM();
        this.BindingContext = this.vm;
    }

    private void Order_ItemTapped(object sender, ItemTappedEventArgs e)
    {
        // Future use to populate OrderItemDetail Page
    }
}

ViewModel 1 "OpenWOrdersVM"

using ApexHQ_Mobile.Models;
using ApexHQ_Mobile.Services.Database;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace ApexHQ_Mobile.ViewModels;

internal partial class OpenWOrdersVM : ObservableObject
{
    public WarehouseOrder order {  get; set; }

    [ObservableProperty]
    private ObservableCollection<WarehouseOrder> orders = new();

    //Initialize View Model in the constructor
    public OpenWOrdersVM()
    {
        orders.Clear();
        orders = new ObservableCollection<WarehouseOrder>(WarehoueOrderService.GetWarehoueOrders());
    }

    [RelayCommand]
    public void GoBack()
    {
        Shell.Current.GoToAsync("..");
    }

    [RelayCommand]
    public void ShowOrderList()
    {
        Shell.Current.GoToAsync("..");
    }
}

ViewModel 2 "WOrderItemsVM"

using ApexHQ_Mobile.Models;
using ApexHQ_Mobile.Services.Database;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;


namespace ApexHQ_Mobile.ViewModels
{
    public partial class WOrderItemsVM: ObservableObject
    {
        private WOItem item { get; set; }

        private ObservableCollection<WOItem> items = new();

        private long orderId;
        public long OrderId
        {
            get => orderId;

            set => SetProperty(ref orderId, value);
        }

        public ObservableCollection<WOItem> Items
        {
            get => items;
            set => SetProperty(ref items, value);
        }

        //public ObservableCollection<WOItem> Items { get { return items; } }

        public void GetOrderItems()
        {
            try
            {
                Items.Clear();
                var items = new ObservableCollection<WOItem>(WarehoueOrderService.GetOrderItemsById(orderId));
                if (items != null)
                {
                    foreach (var item in items)
                    {
                        Items.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {

                throw;
            }
        }

        //public WOrderItemsVM()
        //{
        //    GetOrderItems();
        //}
    }
}

页面路由 AppShell.xaml.cs

using ApexHQ_Mobile.Pages;
namespace ApexHQ_Mobile;

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();

        //Page Route
        Routing.RegisterRoute(nameof(MainPage), typeof(MainPage));
        Routing.RegisterRoute(nameof(OpenOrdersPage), typeof(OpenOrdersPage));
        Routing.RegisterRoute(nameof("itemsPage"), typeof(WOrderItemsPage));
    }
}

问题根源与修复方案

核心问题

1. Shell导航的页面实例覆盖

你在Orders_ItemTapped中手动创建WOrderItemsPage并设置ViewModel,但调用Shell.Current.GoToAsync时,Shell会重新实例化WOrderItemsPage,导致你之前设置的ViewModel被页面构造函数里新创建的空ViewModel覆盖,最终ListView无数据。

2. 路由注册语法错误

AppShell.xaml.cs中使用nameof("itemsPage")是错误写法,nameof用于获取类型/变量的名称字符串,此处应该直接使用页面类型的nameof(WOrderItemsPage)或字符串"WOrderItemsPage"。

修复步骤

步骤1:修正Shell路由注册

// 替换原错误路由
Routing.RegisterRoute(nameof(WOrderItemsPage), typeof(WOrderItemsPage));

步骤2:修改导航逻辑,传递参数而非手动创建页面

private async void Orders_ItemTapped(object sender, ItemTappedEventArgs e)
{
    try
    {
        var order = (WarehouseOrder)e.Item;
        // 通过导航参数传递OrderId
        await Shell.Current.GoToAsync($"{nameof(WOrderItemsPage)}?OrderId={order.Id}");
    }
    catch (Exception ex)
    {
         await DisplayAlert("Error", ex.Message, "OK");
        throw;
    }
}

步骤3:修改WOrderItemsPage接收参数并初始化ViewModel

using ApexHQ_Mobile.ViewModels;
namespace ApexHQ_Mobile.Pages;

public partial class WOrderItemsPage : ContentPage
{
    private WOrderItemsVM vm;
    // 添加构造参数接收OrderId
    public WOrderItemsPage(long orderId)
    {
        InitializeComponent();
        vm = new WOrderItemsVM { OrderId = orderId };
        vm.GetOrderItems();
        this.BindingContext = vm;
    }
}

可选优化:简化WOrderItemsVM的集合更新逻辑

public void GetOrderItems()
{
    try
    {
        var fetchedItems = WarehoueOrderService.GetOrderItemsById(orderId);
        Items = fetchedItems != null ? new ObservableCollection<WOItem>(fetchedItems) : new ObservableCollection<WOItem>();
    }
    catch (Exception ex)
    {
        throw;
    }
}

内容的提问来源于stack exchange,提问作者Mike Yim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:24:52