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

MVVM模式下跨页面传递ObservableCollection<Video>失败问题

MVVM模式下跨页面传递ObservableCollection

项目中MVVM模式在其他场景正常运行,但跨页面传递ObservableCollection<Video>时出现异常,具体情况如下:

发送端实现

声明并在构造函数中实例化集合:

[ObservableProperty]
private ObservableCollection<Video> videoList;

//...

public Constructor()
{   
    VideoList = new ObservableCollection<Video>();
}

触发跳转传值的命令:

[RelayCommand]
private async Task CreateCase()
{
    if (0 == VideoList.Count)
    {
        await App.Current.MainPage.DisplayAlert("No video(s) selected", "You must have at least one video selected to add to your new Case.", "", "OK");
        return;
    }

    Dictionary<string, object> param = new Dictionary<string, object>
    {
        { "VideoList", VideoList }
    };

    await Shell.Current.GoToAsync($"//{nameof(CreateCasePage)}", param);
}

已确认字典中成功存入包含3个选中对象的ObservableCollection<Video>。

接收端初始实现

使用QueryProperty特性,属性名称与发送端一致:

[QueryProperty("VideoList", "VideoList")]
public partial class CreateCasePageViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Video> videoList;

    //...

    public Constructor()
    {
        VideoList = new ObservableCollection<Video>();
    }
}

无论是否在构造函数中实例化集合,接收端的VideoList始终为null。

尝试IQueryAttributable接口优化

发送端代码不变,接收端实现IQueryAttributable接口:

public partial class CreateCasePageViewModel : ObservableObject, IQueryAttributable
{
    [ObservableProperty]
    private ObservableCollection<Video> videoList;

    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        VideoList = query["VideoList"] as ObservableCollection<Video>;
    }
}

断点显示ApplyQueryAttributes方法内VideoList已正确填充,但在ViewModel其他方法中访问时抛出异常。


解决方案

1. 检查Video类的序列化兼容性

Shell导航传递对象时底层可能会尝试序列化,确保Video类满足:

  • 拥有无参构造函数
  • 所有需传递的属性为公共可读写
  • 若使用自定义序列化,类需标记[Serializable]或对应序列化特性

2. 移除构造函数中的集合初始化

接收端构造函数中提前实例化VideoList会覆盖传值逻辑的结果,建议修改构造函数:

public Constructor()
{
    // 不初始化VideoList,由传值逻辑赋值
}

3. 确保ViewModel生命周期匹配

检查CreateCasePage的ViewModel实例逻辑:

  • 确认页面BindingContext在导航后赋值,而非提前创建
  • 若用依赖注入,设置ViewModel为瞬态(Transient),保证每次导航生成新实例

4. 强类型转换并捕获异常

在ApplyQueryAttributes中替换as为强类型转换,便于排查转换问题:

public void ApplyQueryAttributes(IDictionary<string, object> query)
{
    if (query.TryGetValue("VideoList", out var value))
    {
        try
        {
            VideoList = (ObservableCollection<Video>)value;
        }
        catch (InvalidCastException ex)
        {
            System.Diagnostics.Debug.WriteLine($"类型转换失败:{ex.Message}");
        }
    }
}

5. 保证集合访问在主线程

若ViewModel其他方法涉及UI操作,需在主线程访问集合:

MainThread.BeginInvokeOnMainThread(() =>
{
    foreach(var video in VideoList)
    {
        // 处理UI相关逻辑
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:49:51