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

MVVM模式下CollectionView选中项数据传递至新页面的最佳方案

在MVVM模式下传递已加载的ClientesCrm数据到详情页(无需重复请求)

针对你的场景,以下是几种符合MVVM规范、无需重新请求数据的最优实现方案:


方案一:Shell导航参数传递(推荐,原生规范)

利用Shell导航的参数传递机制,将已加载的ClientesCrm对象序列化后通过URL参数传递,详情页ViewModel再反序列化获取数据。

修改ListPageViewModel的OnItemSelected方法

async void OnItemSelected(ClientesCrm item)
{
    if (item == null)
        return;
    
    // 序列化对象并转义URL安全格式
    var clienteJson = Uri.EscapeDataString(JsonSerializer.Serialize(item));
    // 带参数导航到详情页
    await Shell.Current.GoToAsync($"clientesdetalles?SelectedCliente={clienteJson}");
    
    // 重置选中项,避免重复触发导航
    SelectedItem = null;
}

DetailPageViewModel实现IQueryAttributable接口接收参数

public class DetailPageViewModel : BaseViewModel, IQueryAttributable
{
    private ClientesCrm _selectedCliente;
    public ClientesCrm SelectedCliente
    {
        get => _selectedCliente;
        set => SetProperty(ref _selectedCliente, value);
    }

    public void ApplyQueryAttributes(IDictionary<string, string> query)
    {
        if (query.TryGetValue("SelectedCliente", out string clienteJson))
        {
            // 反序列化获取原始对象
            SelectedCliente = JsonSerializer.Deserialize<ClientesCrm>(Uri.UnescapeDataString(clienteJson));
        }
    }
}

优点:完全符合Shell导航的MVVM规范,无需全局状态,参数传递轨迹清晰,适配大多数场景。


方案二:全局共享服务传递(适合复杂场景)

通过依赖注入创建一个临时共享服务,用来存储选中的ClientesCrm对象,详情页ViewModel直接从服务中读取。

1. 创建共享服务接口与实现

public interface ISelectedClienteService
{
    ClientesCrm SelectedCliente { get; set; }
}

public class SelectedClienteService : ISelectedClienteService
{
    public ClientesCrm SelectedCliente { get; set; }
}

2. 在App中注册服务(依赖注入)

// 在App.xaml.cs的CreateMauiApp方法中添加
builder.Services.AddSingleton<ISelectedClienteService>();

3. ListPageViewModel注入服务并设置数据

private readonly ISelectedClienteService _selectedClienteService;

// 通过构造函数注入服务
public ListPageViewModel(ISelectedClienteService selectedClienteService)
{
    _selectedClienteService = selectedClienteService;
}

async void OnItemSelected(ClientesCrm item)
{
    if (item == null)
        return;
    
    // 将选中项存入共享服务
    _selectedClienteService.SelectedCliente = item;
    await Shell.Current.GoToAsync("clientesdetalles");
    
    SelectedItem = null;
}

4. DetailPageViewModel注入服务并读取数据

private readonly ISelectedClienteService _selectedClienteService;

public DetailPageViewModel(ISelectedClienteService selectedClienteService)
{
    _selectedClienteService = selectedClienteService;
    // 从服务中获取选中项
    SelectedCliente = _selectedClienteService.SelectedCliente;
    
    // 可选:读取后清空服务中的数据,避免内存泄漏或数据残留
    _selectedClienteService.SelectedCliente = null;
}

优点:适合多页面共享数据的复杂场景,无需序列化对象,代码简洁。


方案三:构造函数直接传递(小型项目首选)

导航时手动实例化详情页ViewModel,直接将ClientesCrm对象通过构造函数传入。

修改ListPageViewModel的OnItemSelected方法

async void OnItemSelected(ClientesCrm item)
{
    if (item == null)
        return;
    
    // 直接传入选中项实例化ViewModel
    var detailViewModel = new DetailPageViewModel(item);
    var detailPage = new DetailPage { BindingContext = detailViewModel };
    
    await Shell.Current.Navigation.PushAsync(detailPage);
    SelectedItem = null;
}

DetailPageViewModel构造函数接收参数

public class DetailPageViewModel : BaseViewModel
{
    private ClientesCrm _selectedCliente;
    public ClientesCrm SelectedCliente
    {
        get => _selectedCliente;
        set => SetProperty(ref _selectedCliente, value);
    }

    // 通过构造函数接收选中项
    public DetailPageViewModel(ClientesCrm cliente)
    {
        SelectedCliente = cliente;
    }
}

优点:实现最简单,无需额外配置,适合小型或快速迭代的项目。


通用注意事项

  • 所有方案中,导航完成后都要重置SelectedItem为null,避免用户重复点击同一项时触发多次导航。
  • 如果ClientesCrm包含复杂嵌套对象,序列化时需确保属性可被正确序列化(可使用Newtonsoft.Json替代System.Text.Json处理复杂场景)。

内容的提问来源于stack exchange,提问作者Oswaldo Roosemberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:58:19