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

Android应用中ObservableCollection数据无法显示在CollectionView的问题

CollectionView添加车辆后无法自动更新列表的问题解决

我测试一款Android端移动应用时,遇到了数据从ViewModel传递到UI的CollectionView的问题——主菜单显示车辆列表,但添加车辆后,列表无法自动更新。

之前按要求定义了两个ObservableCollection:

ObservableCollection<AutoWithSwitch> MyList = new ObservableCollection<AutoWithSwitch>();
public ObservableCollection<AutoWithSwitch> AutoData
{
    get { return MyList; }
    set { MyList = value; }
}

填充MyList后赋值给CollectionView的ItemSource(AutoData)的逻辑在其他场景正常,但添加车辆后失效。以下是关键代码:

EnterCarViewModel中添加车辆的代码

int results = await repository.AddAutoData(data);

if (results == 1)
{
    IsVisibleResults = true;
    EntResults = "Entered Successfully";
    if (Convert.ToBoolean(Preferences.Default.Get("firstAutoEntered", false)))
    {
        Preferences.Set("autoId", 1);
        Preferences.Set("firstAutoEntered", false);
    }
                                   
    Preferences.Set("CarAdded", true);                    
    mmvm.GetMyCars(await repository.GetAuto());                    
    await Shell.Current.GoToAsync("///MainPage");
}
public async void GetMyCars(List<AutoTableDefination> atd)
{
    try
    {
        bool processed = false;
        MileageItemRepository repo = new MileageItemRepository();
        MyList = new ObservableCollection<AutoWithSwitch>();
        AutoData = new ObservableCollection<AutoWithSwitch>();
        var autoId = Convert.ToInt32(Preferences.Get("autoId", 0));
   
        if (atd.Count > 0)
        {
            foreach (var item in atd)
            {
                if (item.CarDesc.ToUpper() == Preferences.Default.Get("UpperCar", string.Empty))
                {
                    if (item.Id == autoId)
                    {
                        item.CarDesc = item.CarDesc.ToUpper();
                        Preferences.Default.Set("UpperCar", item.CarDesc.ToUpper());
                        Preferences.Default.Set("autoId", item.Id);
                    }
                }
                if (item.IsDefault)
                    item.CarDesc = "**" + item.CarDesc;

                if (item.IsDefault && !processed)
                {
                    Preferences.Default.Set("autoId", item.Id);
                }
            
                Preferences.Default.Set("enter1stCar", false);
                if (!processed)
                {                                                        
                   processed = false;                                                       
               }
                MyList.Add(new AutoWithSwitch { Id = item.Id, Name = item.CarDesc });
            }
            var sortedList =
                MyList.OrderBy(x => x.Name);
            
            MyList = new ObservableCollection<AutoWithSwitch>(sortedList);
        
            AutoData = MyList;
            MainPage mainPage = new MainPage(AutoData, cv);
            //cv.ItemsSource = null;
            //cv.ItemsSource = AutoData;
            processed = true;                    
        }                
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    if (Convert.ToBoolean(Preferences.Get("CarAdded", true)))
        Device.BeginInvokeOnMainThread(async () => { await 
App.Current.MainPage.DisplayAlert("Success", "Car successfully added", "Ok"); });
}

尝试过直接设置ItemsSource、通过MainPage构造函数传递数据两种方式,均无效,寻求解决方案。


问题根源

  1. AutoData未实现属性变更通知:直接赋值新的ObservableCollection时,UI无法感知属性变化,因为没有触发PropertyChanged事件。
  2. 重复实例化集合破坏绑定:每次调用GetMyCars都新建集合实例,原UI绑定的是旧实例,新数据无法同步。
  3. 错误创建新页面实例:MainPage mainPage = new MainPage(AutoData, cv);生成了未显示的新页面,当前展示的旧页面不会更新。

修复步骤

1. 让ViewModel实现INotifyPropertyChanged

确保MainMenuViewModel实现属性变更通知接口,让UI感知属性变化:

public class MainMenuViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private ObservableCollection<AutoWithSwitch> _myList = new ObservableCollection<AutoWithSwitch>();
    public ObservableCollection<AutoWithSwitch> AutoData
    {
        get { return _myList; }
        set 
        { 
            _myList = value;
            OnPropertyChanged(); // 触发属性变更通知
        }
    }
}

2. 复用集合实例,避免重新创建

清空现有集合再添加新数据,保持绑定的集合实例不变,UI会自动感知内容变化:

public async void GetMyCars(List<AutoTableDefination> atd)
{
    try
    {
        bool processed = false;
        MileageItemRepository repo = new MileageItemRepository();
        var autoId = Convert.ToInt32(Preferences.Get("autoId", 0));
   
        if (atd.Count > 0)
        {
            // 清空现有集合,而非重新实例化
            Device.BeginInvokeOnMainThread(() => AutoData.Clear());
            
            var tempList = new List<AutoWithSwitch>();
            foreach (var item in atd)
            {
                if (item.CarDesc.ToUpper() == Preferences.Default.Get("UpperCar", string.Empty))
                {
                    if (item.Id == autoId)
                    {
                        item.CarDesc = item.CarDesc.ToUpper();
                        Preferences.Default.Set("UpperCar", item.CarDesc.ToUpper());
                        Preferences.Default.Set("autoId", item.Id);
                    }
                }
                if (item.IsDefault)
                    item.CarDesc = "**" + item.CarDesc;

                if (item.IsDefault && !processed)
                {
                    Preferences.Default.Set("autoId", item.Id);
                }
            
                Preferences.Default.Set("enter1stCar", false);
                if (!processed)
                {                                                        
                   processed = false;                                                       
               }
                tempList.Add(new AutoWithSwitch { Id = item.Id, Name = item.CarDesc });
            }
            // 排序后在UI线程添加到集合
            var sortedList = tempList.OrderBy(x => x.Name);
            Device.BeginInvokeOnMainThread(() => {
                foreach (var auto in sortedList)
                {
                    AutoData.Add(auto);
                }
            });
            
            processed = true;                    
        }                
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    if (Convert.ToBoolean(Preferences.Get("CarAdded", true)))
        Device.BeginInvokeOnMainThread(async () => { await 
App.Current.MainPage.DisplayAlert("Success", "Car successfully added", "Ok"); });
}

3. 移除多余的页面实例创建

删除MainPage mainPage = new MainPage(AutoData, cv);代码,当前显示的MainPage已绑定集合,更新集合内容即可同步UI。


内容的提问来源于stack exchange,提问作者Steve H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:39