【问题标题】:Not seeing any data in Xamarin CollectionView在 Xamarin CollectionView 中看不到任何数据
【发布时间】:2021-10-11 11:27:05
【问题描述】:

我正在学习 Xamarin,我正在尝试制作一个应用程序,我可以在其中浏览屏幕中的一些元素,然后单击元素打开一个新屏幕。我尝试使用弹出模板,并在第一个屏幕上使用模板中的 collectionview 逻辑。但是,使用相同的逻辑,我没有在我的集合视图中看到任何数据。这是我的模型、视图、视图模型以及 xaml 和 cs 文件。 型号:

public class VehicleMake
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Abrv { get; set; }
    }

查看:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             BackgroundColor="LightCoral"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:VehicleProject.ViewModels" 
             xmlns:model="clr-namespace:VehicleProject.Models" 
             x:DataType="local:VehicleMakeViewModel"
             x:Class="VehicleProject.Views.VehicleMakePage">
    <RefreshView x:DataType="local:VehicleMakeViewModel" Command="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
    <CollectionView x:Name="ItemsListView"
                ItemsSource="{Binding VehicleMakes}"
                SelectionMode="None">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <StackLayout Padding="10" x:DataType="model:VehicleMake" BackgroundColor="White">
                    <Label Text="{Binding Id}" 
                           TextColor="White"
                            LineBreakMode="NoWrap" 
                            Style="{DynamicResource ListItemTextStyle}" 
                            FontSize="16" />
                    <Label Text="{Binding Name}" 
                            LineBreakMode="NoWrap"
                            Style="{DynamicResource ListItemDetailTextStyle}"
                            FontSize="13" />
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer 
                                NumberOfTapsRequired="1"
                                Command="{Binding Source={RelativeSource AncestorType={x:Type local:VehicleModelViewModel}}, Path=ItemTapped}"      
                                CommandParameter="{Binding .}">
                        </TapGestureRecognizer>
                    </StackLayout.GestureRecognizers>
                </StackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    </RefreshView>
</ContentPage>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VehicleProject.ViewModels;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace VehicleProject.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class VehicleMakePage : ContentPage
    {
        VehicleMakeViewModel _viewModel;
        public VehicleMakePage()
        {
            InitializeComponent();
            BindingContext = _viewModel = new VehicleMakeViewModel();
        }
        protected override void OnAppearing()
        {
            base.OnAppearing();
            _viewModel.OnAppearing();
        }
    }
}

视图模型:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using VehicleProject.Models;
using Xamarin.Forms;

namespace VehicleProject.ViewModels
{
    public class VehicleMakeViewModel: BaseViewModel
    {
        private VehicleMake _selectedItem;
        public ObservableCollection<VehicleMake> VehicleMakes { get; set; } = new ObservableCollection<VehicleMake>();
        public Command LoadItemsCommand { get; }
        public Command AddItemCommand { get; }
        public Command<VehicleMake> ItemTapped { get; }

        public VehicleMakeViewModel()
        {
            Title = "Vehicles";
            VehicleMakes = new ObservableCollection<VehicleMake>();
            LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());

            ItemTapped = new Command<VehicleMake>(OnItemSelected);

            AddItemCommand = new Command(OnAddItem);
        }

        async Task ExecuteLoadItemsCommand()
        {
            IsBusy = true;

            try
            {
                VehicleMakes.Clear();
                var vehicleMakes = await DataStore.GetItemsAsync(true);
                foreach (var vehicleMake in vehicleMakes)
                {
                    Debug.WriteLine(vehicleMake.Id);
                    VehicleMakes.Add(vehicleMake);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            finally
            {
                IsBusy = false;
            }
        }
        public void OnAppearing()
        {
            IsBusy = true;
            SelectedItem = null;
        }

        public VehicleMake SelectedItem
        {
            get => _selectedItem;
            set
            {
                SetProperty(ref _selectedItem, value);
                OnItemSelected(value);
            }
        }

        private async void OnAddItem(object obj)
        {
            //await Shell.Current.GoToAsync(nameof(NewItemPage));
        }

        async void OnItemSelected(VehicleMake item)
        {
            if (item == null)
                return;

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

BaseViewModel:

public class BaseViewModel :  INotifyPropertyChanged
    {
        public IDataStore<VehicleMake> DataStore => DependencyService.Get<IDataStore<VehicleMake>>();

    bool isBusy = false;
    public bool IsBusy
    {
        get { return isBusy; }
        set { SetProperty(ref isBusy, value); }
    }

    string title = string.Empty;
    public string Title
    {
        get { return title; }
        set { SetProperty(ref title, value); }
    }

    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName] string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

IDataStore:

    public interface IDataStore<T>
        {
            Task<bool> AddItemAsync(T item);
            Task<bool> UpdateItemAsync(T item);
            Task<bool> DeleteItemAsync(string id);
            Task<T> GetItemAsync(string id);
            Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false);
        }

MockVehicleMakeStore:

public class MockVehicleMakeStore : IDataStore<VehicleMake>
    {
        readonly List<VehicleMake> vehicleMakes;

        public MockVehicleMakeStore()
        {
            vehicleMakes = new List<VehicleMake>()
            {
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "First item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Second item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Third item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Fourth item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Fifth item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Sixth item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Sixth item", Abrv="This is an item description." },
                new VehicleMake { Id = Guid.NewGuid().ToString(), Name = "Sixth item", Abrv="This is an item description." }

            };
        }
        public async Task<bool> AddItemAsync(VehicleMake item)
        {
            vehicleMakes.Add(item);

            return await Task.FromResult(true);
        }
        public async Task<bool> UpdateItemAsync(VehicleMake item)
        {
            var oldItem = vehicleMakes.Where((VehicleMake arg) => arg.Id == item.Id).FirstOrDefault();
            vehicleMakes.Remove(oldItem);
            vehicleMakes.Add(item);

            return await Task.FromResult(true);
        }

        public async Task<bool> DeleteItemAsync(string id)
        {
            var oldItem = vehicleMakes.Where((VehicleMake arg) => arg.Id == id).FirstOrDefault();
            vehicleMakes.Remove(oldItem);

            return await Task.FromResult(true);
        }

        public async Task<VehicleMake> GetItemAsync(string id)
        {
            return await Task.FromResult(vehicleMakes.FirstOrDefault(s => s.Id == id));
        }

        public async Task<IEnumerable<VehicleMake>> GetItemsAsync(bool forceRefresh = false)
        {
            return await Task.FromResult(vehicleMakes);
        }
    }

我的解决方案的逻辑与模板中的逻辑相同,但似乎我正在监督一些事情。请帮忙。谢谢

【问题讨论】:

  • 是自动执行,还是手动触发刷新?无论哪种方式,您都应该验证您的虚拟机确实包含数据
  • 您需要使用调试器来验证您的加载命令是否正在执行,以及它是否实际正在加载数据
  • 某事为空。弄清楚它是什么并修复它。堆栈跟踪应该准确地告诉您是哪一行导致它。这是基本的 C# 调试。
  • 您检查过DataStore 是否为空吗?
  • 我第三次将相同的逻辑应用于一个新的项目模板,现在它可以工作了。 DataStore 无法正常工作,因为它没有被初始化。谢谢

标签: c# xamarin xamarin.forms collectionview


【解决方案1】:

所以问题是我的 DependencyService 没有注册.... 在 app.xaml.cs 中,我在其构造函数中添加了这一行,就在 InitializeComponent(); 之后 依赖服务.Register();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    相关资源
    最近更新 更多