如何将ObservableCollection从ViewModelA传递到MVVM中的ViewModelB

时间:2016-03-15 21:05:54

标签: c# mvvm xamarin mvvmcross

我正在尝试将信息从ViewModelA传递到ViewModelB,如下所示。当我调试代码时,我能够观察到我的SCoordinates中有5个对象,但当我尝试在ViewModelB中获取这5个对象时,它将变为空。其他信息(日期,sId)不为空,只有SCoordinates为空。

ViewModelA

public ObservableCollection<SVModel> SCoordinates 
{
   get { return _sp; }
   set
   {
     _sp = value;
     RaisePropertyChanged(() => SCoordinates );
   }
 }

private void SSelected(SVModel obj)
{
   ShowViewModel<ViewModelB>(new { sId = obj.Id, date = DateTime.Now, sCoordinates = SCoordinates });
}

ViewModelB

public void Init(string sId, DateTime date, ObservableCollection<SVModel> sCoordinates)
 {
   var sp = _sService.GetService(sId);
   SVModel = new SVModel (sp);
  // the following gets null
   SCoordinates = sCoordinates;
}

2 个答案:

答案 0 :(得分:4)

正如documentation明确指出:

  

请注意,由于序列化要求,此技术中使用的唯一可用参数类型仅为:

     
      
  • 它必须包含无参数构造函数
  •   
  • 它应该只包含具有get和set访问权限的公共属性
  •   
  • 这些属性应仅包含以下类型:      
        
    • int,long,double,string,Guid,枚举值
    •   
  •   

换句话说,只支持使用valuetype作为参数的成员。

我认为这是MvvmCross的一个重大设计缺陷。我不是说这应该得到支持,但如果不遵循文档中的约束,框架应该抛出异常。因此,不是默默地接受传递不符合约束的类并传递null,而是应该抛出一个明确的异常框架。从而通知您,而不是让您在这里搜索答案。

这种理念甚至有一个名称:Fail fast!

答案 1 :(得分:2)

我可以在这里考虑3个选项:

1){糟糕的做法,但很简单}创建一个服务(默认情况下在mvvmcross中单独使用)来保存您的SCoordinates集合,而不是将它们保留在ViewModel中。这可能被认为是不好的做法,因为服务应该是无国籍的。虽然它会起作用。

<强>更新

作为评论问题的答案,这是一个例子。如果你使用MvvmCross,你应该熟悉这个:

public class App : MvxApplication
{
    public override void Initialize()
    {
        CreatableTypes()
            .EndingWith("Service")
            .AsInterfaces()
            .RegisterAsLazySingleton();

        /// ...
    }
}

因此,您创建一个以“Service”结尾的简单类以及核心项目中的相应接口。

public interface ICoordinatesService
{
    ObservableCollection<SVModel> Coordinates { get; set; }
}

public class CoordinatesService : ICoordinatesService
{
    public ObservableCollection<SVModel> Coordinates { get; set; }
}

要访问viewmodel中的服务,您可以使用constructor injection并无需使用方法即可访问服务中托管的集合,更简单的方法如下:

public class YourViewModel : MvxViewModel
{
    public ObservableCollection<SVModel> Coordinates => _coordinatesService.Coordinates;

    private readonly ICoordinatesService _coordinatesService;

    public YourViewModel(ICoordinatesService coordinatesService)
    {
        _coordinatesService = coordinatesService;
    }

    public void SaveSomeCoordinates()
    {
        Coordinates.Add(new SVModel());
    }

    public void RemoveSomeCoordinates()
    {
        Coordinates.RemoveAt(1);
    }

    public void ResetCoordinates()
    {
        _coordinatesService.Coordinates = new ObservableCollection<SVModel>();
    }
}

2)使用本地缓存系统保存SCoordinates。您可以通过服务来完成:

public class Service
{
    public ObservableCollection<SVModel> RestoreCoordinates() 
    {
         // get from cache
    }
    public bool SaveCoordinates(ObservableCollection<SVModel> coordinates) 
    {
        // save to cache
    }
}

然后,在ViewModel.Init()上,您可以恢复数据。

我建议使用Akavache作为简单的本地缓存,但您可以使用其他库或简单的SQLite表

3)Serialize your collection with Json.Net并将其作为字符串传递给ShowViewModel() init params。然后在Init()方法

上反序列化它