【问题标题】:Not adding the element in observable collection properly, id from past activity not passed properly未在可观察集合中正确添加元素,过去活动的 id 未正确传递
【发布时间】:2021-08-09 12:07:35
【问题描述】:

我是 Xamarin 的新手,我正在制作一个应用程序,其中在屏幕 1 上显示车辆制造商列表,单击集合视图中表示的某个制造商时,我将显示他们的车辆列表用户可以更改制造商名称及其缩写,并对其进行更新、删除制造商和添加新车辆。问题是当我添加新车时,它似乎没有添加到那个制造商,它的 ID 似乎没有定义。我将 id 传递给新视图,但看起来我做得不对,因为车辆不会出现在列表中(当我关闭车辆制造商过滤器时(评论 if (item.MakeId == itemId)在 VehicleMakeViewModel 的 ExecuteLoadItemsCommand 中),我可以看到车辆已添加,但 id 不是我要设置的那个,它是空的。)我可能做错了什么或忽略了某些东西,所以请如果你能看到问题, 帮我。在 VehicleMakeViewModel 中,我正在执行添加新车、删除和更新制造商的逻辑,在 NewVehicleModelViewModel 中,我让用户输入新车的信息。 VehicleMakeViewModel:

namespace App3.ViewModels
{
    [QueryProperty(nameof(ItemId), nameof(ItemId))]
    public class VehicleMakeDetailViewModel : BaseViewModel
    {

        private VehicleModel _selectedItem;

        public ObservableCollection<VehicleModel> VehicleModels { get; }
        public Command LoadVehicleModelsCommand { get; }
        public Command AddVehicleModelCommand { get; }

        public Command<VehicleModel> VehicleModelTapped { get; }

        public Command DeleteVehicleMakeCommand { get; }

        public Command UpdateVehicleMakeCommand { get; }

        public VehicleMakeDetailViewModel()
        {
            Title = "Vehicles";
            VehicleModels = new ObservableCollection<VehicleModel>();
            LoadVehicleModelsCommand = new Command(async () => await ExecuteLoadItemsCommand());

            VehicleModelTapped = new Command<VehicleModel>(OnVehicleModelSelected);

            AddVehicleModelCommand = new Command(OnAddItem);

            UpdateVehicleMakeCommand = new Command(UpdateItem);
            DeleteVehicleMakeCommand = new Command(DeleteItem);
        }

        async Task ExecuteLoadItemsCommand()
        {
            IsBusy = true;

            try
            {
                VehicleModels.Clear();
                var items = await BaseVehicleModelDataStore.GetItemsAsync(true);
                foreach (var item in items)
                {
                    //if (item.MakeId == itemId)
                        VehicleModels.Add(item);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            finally
            {
                IsBusy = false;
            }
        }


        public void OnAppearing()
        {
            IsBusy = true;
            SelectedItem = null;
        }
        public VehicleModel SelectedItem
        {
            get => _selectedItem;
            set
            {
                SetProperty(ref _selectedItem, value);
                OnVehicleModelSelected(value);
            }
        }

        async void OnVehicleModelSelected(VehicleModel item)
        {
            if (item == null)
                return;

            // This will push the ItemDetailPage onto the navigation stack
            await Shell.Current.GoToAsync($"{nameof(VehicleModelDetailPage)}?{nameof(VehicleModelDetailViewModel.ItemId)}={item.Id}");
        }

        private async void DeleteItem(object obj)
        {
            try
            {
                foreach(var item in VehicleModels)
                {
                    if (item.MakeId == Id)
                    {
                        await BaseVehicleModelDataStore.DeleteItemAsync(item.Id);
                    }
                }
                await BaseVehicleMakeDataStore.DeleteItemAsync(Id);
                
                await Shell.Current.GoToAsync(nameof(VehicleMakesPage));
                /*ItemId = "";
                VehicleMakeAbrv = "";
                VehicleMakeName = "";*/
                //App.Current.MainPage = new VehicleMakesPage();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }

        private async void UpdateItem(object obj)
        {
            try
            {
                await BaseVehicleMakeDataStore.UpdateItemAsync(new VehicleMake { Id= Id, Name = VehicleMakeName, Abrv=VehicleMakeAbrv });
                foreach(var item in VehicleModels)
                {
                    if (item.MakeId == Id)
                    {
                        await BaseVehicleModelDataStore.UpdateItemAsync(new VehicleModel { Id = item.Id, Name = item.Name, Abrv = item.Abrv, MakeId = item.MakeId });
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }

        private async void OnAddItem(object obj)
        {
            await Shell.Current.GoToAsync($"{nameof(NewVehicleModelPage)}?{nameof(NewVehicleModelViewModel.ItemId)}={ItemId}");
        }

        private string itemId;
        private string vehicleMakeName;
        private string vehicleMakeAbrv;
        public string Id { get; set; }

        public string VehicleMakeName
        {
            get => vehicleMakeName;
            set => SetProperty(ref vehicleMakeName, value);
        }

        public string VehicleMakeAbrv
        {
            get => vehicleMakeAbrv;
            set => SetProperty(ref vehicleMakeAbrv, value);
        }

        public string ItemId
        {
            get
            {
                return itemId;
            }
            set
            {
                itemId = value;
                LoadItemId(value);
            }
        }

        public async void LoadItemId(string itemId)
        {
            try
            {
                var item = await BaseVehicleMakeDataStore.GetItemAsync(itemId);
                Id = item.Id;
                VehicleMakeName = item.Name;
                VehicleMakeAbrv = item.Abrv;
                Title = Id;
            }
            catch (Exception)
            {
                Debug.WriteLine("Failed to Load Item");
            }
        }
    }
}

NewVehicleModelViewModel:

namespace App3.ViewModels
{
    class NewVehicleModelViewModel: BaseViewModel
    {
        private string text;
        private string description;
        private string itemId;

        public NewVehicleModelViewModel()
        {
            SaveCommand = new Command(OnSave, ValidateSave);
            CancelCommand = new Command(OnCancel);
            this.PropertyChanged +=
                (_, __) => SaveCommand.ChangeCanExecute();
            Text = ItemId;
            Description = ItemId;
        }

        private bool ValidateSave()
        {
            return !String.IsNullOrWhiteSpace(text)
                && !String.IsNullOrWhiteSpace(description);
        }
        public string ItemId
        {
            get
            {
                return itemId;
            }
            set
            {
                itemId = value;
                //LoadItemId(value);
            }
        }

        public async void LoadItemId(string itemId)
        {
            try
            {
                var item = await BaseVehicleMakeDataStore.GetItemAsync(itemId);
                ItemId = item.Id;
                //VehicleMakeName = item.Name;
                //VehicleMakeAbrv = item.Abrv;
            }
            catch (Exception)
            {
                Debug.WriteLine("Failed to Load Item");
            }
        }

        public string Text
        {
            get => text;
            set => SetProperty(ref text, value);
        }

        public string Description
        {
            get => description;
            set => SetProperty(ref description, value);
        }

        public Command SaveCommand { get; }
        public Command CancelCommand { get; }

        private async void OnCancel()
        {
            // This will pop the current page off the navigation stack
            await Shell.Current.GoToAsync("..");
        }

        private async void OnSave()
        {
            VehicleModel newItem = new VehicleModel()
            {
                Id = Guid.NewGuid().ToString(),
                Name = Text,
                Abrv = Description,
                MakeId = ItemId
            };

            await BaseVehicleModelDataStore.AddItemAsync(newItem);

            // This will pop the current page off the navigation stack
            await Shell.Current.GoToAsync("..");
        }
    }
}

【问题讨论】:

  • 在 NewVehicleModelViewModel 中添加新车辆后,您似乎没有做任何事情来刷新或重新加载 VehicleMakeDetailViewModel 中的数据
  • 是的,但是当我不检查它是否与车辆制造商具有相同的 ID 并且实际上我看到它没有相同的 ID 时,我可以在添加它时看到新车,我将id绑定到collectionview中的一个标签,它是空的。问题似乎与 ID 相关

标签: c# xamarin xamarin.forms observablecollection


【解决方案1】:

我在 NewVehicleModelViewModel 类之前缺少 QueryProperty。 所以 NewVehicleModelViewModel 类看起来像这样:

namespace App3.ViewModels
{
    [QueryProperty(nameof(ItemId), nameof(ItemId))]
    class NewVehicleModelViewModel: BaseViewModel
    {
... //other things are the same..

【讨论】:

  • FWIW:除非有人仔细阅读您的代码,否则不明显的是,这些视图模型适用于 Shell 应用程序。 QueryProperty 是使用 Shell 导航时的一项功能。在这种情况下,显示使用这些模型的 XAML 页面会为问题提供更多上下文;更容易帮助你。 (我提到作为对您将来提出的问题的建议。)
  • 另外,在描述问题时,将其分解成小块。 (不是没有人会仔细阅读的 12 行段落。)并将其与代码联系起来。 “当我添加一辆新车等等等等”(然后是一个显示添加新车的代码的代码块),我期望......(理想情况下,一个特定的变量或 XAML 元素,以及它应该包含的内容),而是[这发生了]。然后是一个新的段落:“我可以看到添加了车辆,但是id不是我要设置的那个,它是空的。” - 再次,代码在哪里?什么变量应该有 id?
  • @ToolmakerSteve 好的,我会记住这一点,不知道这是特定于 Shell 的,因为这基本上是我的第一个项目,我只是在学习。谢谢你的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 2011-09-15
  • 2012-11-07
  • 1970-01-01
相关资源
最近更新 更多