与 ObservableCollection 的双向数据绑定问题

问题描述 投票:0回答:1

我的项目中有三个页面,其中有两个

ViewModels
和两个模型。第一页将未结订单填充到
ListView 
中,没有任何问题。当点击第一页代码中的
ListView 
项目 (
Orders_ItemTapped
) 时,其后面的代码应该将订单项目填充到第二页的
ListView 
中。但第二页显示空白
ListView

我在调试时没有任何错误,并且点击的事件正在调用所有方法,但似乎没有任何效果。经过进一步研究,问题似乎来自两种方式的数据绑定问题或我使用

ViewModel
或在第一页的 Taped 事件中实例化
ViewModel 
和方法的方式。

为了进一步测试,我对

GetOrderItemsById()
进行了硬编码,以填充第二个
list<>
的构造函数中的
ViewModel 
,并且它正确地将所有订单项显示到第二页。

我不熟悉依赖注入尝试,但我想了解我当前的方法做错了什么。我猜我的问题与我在

ObservableCollection
中使用
ViewModel
属性/构造函数或在点击事件中实例化
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(WOrderItemsPage));
        }
        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(WOrderItemsPage), typeof(WOrderItemsPage));
    }
}
maui observablecollection
1个回答
0
投票

Orders_ItemTapped 中,您正在初始化一个新的 WOrderItemsPage 并将页面的绑定上下文设置为您的第一页虚拟机。

  var itemsPage = new WOrderItemsPage();
  itemsPage.BindingContext = vm;

但是你从未使用过新创建的页面对象。 您只需使用导航到页面的另一个新实例。

Shell.Current.GoToAsync(nameof(WOrderItemsPage));

上面的导航调用将创建页面的新实例,然后创建构造函数中定义的视图模型的新实例。

尝试 PushAsync() 并传递您创建的页面对象并检查。

Shell.Current.PushAsync(itemsPage);
© www.soinside.com 2019 - 2024. All rights reserved.