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

如何在其他ViewModel中访问共享的ObservableCollection?

最佳解决方案

1. 全局单例数据服务(推荐)

创建独立的数据服务类,持有唯一的ObservableCollection<Patient>实例,所有ViewModel通过依赖注入访问同一集合,确保操作的是数据源本身。

步骤1:创建数据服务

public class PatientDataService
{
    public ObservableCollection<Patient> PatientInfo { get; } = new ObservableCollection<Patient>();

    // 加载数据的方法
    public void PopulatePatientData()
    {
        try
        {
            string query = "select * from " + App.userDetails.DbTable;
            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(query, conn);
            using (sqlDataAdapter)
            {
                System.Data.DataTable dt = new System.Data.DataTable();
                sqlDataAdapter.Fill(dt);
                PatientInfo.Clear();
                foreach (System.Data.DataRow row in dt.Rows)
                    PatientInfo.Add(new Patient(Convert.ToInt32(row[0]), row[1].ToString(), row[2].ToString(), row[3].ToString(), row[4].ToString(), row[5].ToString(), row[6].ToString(), row[7].ToString(), row[8].ToString()));
            }
        }
        catch (Exception)
        { }
    }
}

步骤2:注册服务(在MauiProgram.cs中)

builder.Services.AddSingleton<PatientDataService>();

步骤3:修改ViewModel依赖注入

public partial class BaseViewModel : ObservableObject
{
    protected readonly PatientDataService _dataService;

    public ObservableCollection<Patient> PatientInfo => _dataService.PatientInfo;

    public BaseViewModel(PatientDataService dataService)
    {
        _dataService = dataService;
    }
}

// DashboardViewModel中初始化数据
public partial class DashboardViewModel : BaseViewModel
{
    public DashboardViewModel(PatientDataService dataService) : base(dataService)
    {
        _dataService.PopulatePatientData();
    }
}

// EditingViewModel中操作共享集合
[QueryProperty(nameof(Patient), nameof(Patient))]
public partial class EditingViewModel : BaseViewModel
{
    [ObservableProperty] private Patient patient;
    
    public EditingViewModel(PatientDataService dataService) : base(dataService) { }

    [RelayCommand]
    private async Task Delete()
    {
        try
        {
            // 数据库删除逻辑不变
            string query = "DELETE from " + App.userDetails.DbTable + " WHERE id = @patientId";
            sqlConnection = new SqlConnection(conn);
            SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);

            using (sqlDataAdapter)
            {
                sqlConnection.Open();
                sqlCommand.Parameters.AddWithValue("@patientId", Patient.Id);
                sqlCommand.ExecuteScalar();
            }

            // 操作共享的集合
            var targetPatient = PatientInfo.SingleOrDefault(x => x.Id == Patient.Id);
            if (targetPatient != null)
                PatientInfo.Remove(targetPatient);
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert("Aplicaçao", ex.ToString(), "Sair");
        }
        finally
        {
            sqlConnection.Close();
        }
    }
}

2. 使用MVVM Toolkit Messenger传递更新通知

通过消息传递解耦ViewModel,EditingViewModel发送删除通知,DashboardViewModel接收并更新自身的集合。

步骤1:定义消息类

public class PatientDeletedMessage
{
    public int PatientId { get; set; }
}

步骤2:EditingViewModel发送消息

[RelayCommand]
private async Task Delete()
{
    try
    {
        // 数据库删除逻辑不变...

        // 发送删除消息
        WeakReferenceMessenger.Default.Send(new PatientDeletedMessage { PatientId = Patient.Id });
    }
    catch (Exception ex)
    {
        await Shell.Current.DisplayAlert("Aplicaçao", ex.ToString(), "Sair");
    }
    finally
    {
        sqlConnection.Close();
    }
}

步骤3:DashboardViewModel注册消息处理

public partial class DashboardViewModel : BaseViewModel
{
    public DashboardViewModel(IMessenger messenger)
    {
        // 注册消息监听
        messenger.Register<PatientDeletedMessage>(this, (recipient, message) =>
        {
            var patientToRemove = PatientInfo.SingleOrDefault(x => x.Id == message.PatientId);
            if (patientToRemove != null)
                PatientInfo.Remove(patientToRemove);
        });
    }
}

步骤4:注册Messenger服务(MauiProgram.cs)

builder.Services.AddSingleton<IMessenger>(WeakReferenceMessenger.Default);

3. 直接传递集合引用(简单但耦合度高)

跳转至EditingPage时,将DashboardViewModel的PatientInfo集合作为参数传递,让EditingViewModel直接操作该引用。

步骤1:修改EditingViewModel接收集合

[QueryProperty(nameof(Patient), nameof(Patient))]
public partial class EditingViewModel : ObservableObject
{
    private ObservableCollection<Patient> _sharedPatientInfo;
    [ObservableProperty] private Patient patient;

    // 通过QueryProperty接收集合
    [QueryProperty(nameof(SharedPatientInfo), nameof(SharedPatientInfo))]
    public ObservableCollection<Patient> SharedPatientInfo
    {
        get => _sharedPatientInfo;
        set => SetProperty(ref _sharedPatientInfo, value);
    }

    [RelayCommand]
    private async Task Delete()
    {
        try
        {
            // 数据库删除逻辑不变...

            // 操作传递过来的共享集合
            var targetPatient = SharedPatientInfo.SingleOrDefault(x => x.Id == Patient.Id);
            if (targetPatient != null)
                SharedPatientInfo.Remove(targetPatient);
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert("Aplicaçao", ex.ToString(), "Sair");
        }
        finally
        {
            sqlConnection.Close();
        }
    }
}

步骤2:跳转时传递集合参数

// DashboardViewModel中的跳转命令
[RelayCommand]
private async Task NavigateToEdit()
{
    if (SelectedPatient != null)
    {
        await Shell.Current.GoToAsync(nameof(EditingPage), new Dictionary<string, object>
        {
            { nameof(Patient), SelectedPatient },
            { nameof(EditingViewModel.SharedPatientInfo), PatientInfo }
        });
    }
}

方案选型建议
  • 全局数据服务:最适合需要多ViewModel共享同一数据源的场景,逻辑清晰,维护成本低,优先推荐。
  • Messenger消息传递:解耦性强,适合跨模块、跨ViewModel的通知场景,避免直接依赖。
  • 直接传递引用:实现简单,但ViewModel之间耦合度高,适合小型项目或临时需求。

内容的提问来源于stack exchange,提问作者Joao Lima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:24:22