C# 如何在MVVM中将ObservableCollection从ViewModelA传递到ViewModelB

C# 如何在MVVM中将ObservableCollection从ViewModelA传递到ViewModelB,c#,mvvm,xamarin,mvvmcross,C#,Mvvm,Xamarin,Mvvmcross,我正在尝试将信息从ViewModelA传递到ViewModelB,如下所示。当我调试代码时,我可以观察到我的SCoordinates中有5个对象,但当我尝试在ViewModelB中获取这5个对象时,它将为空。其他信息(日期、sId)不为空,只有SCoordinates为空 ViewModelA public ObservableCollection<SVModel> SCoordinates { get { return _sp; } set { _sp

我正在尝试将信息从
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 });
}
公共可观测集合坐标
{
获取{return\u sp;}
设置
{
_sp=值;
RaisePropertyChanged(()=>坐标);
}
}
已选择专用作废(SVModel obj)
{
ShowViewModel(新的{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;
}
public void Init(字符串sId、日期时间日期、可观测集合坐标)
{
var sp=_sService.GetService(sId);
SVModel=新SVModel(sp);
//下面的值为空
坐标轴=坐标轴;
}
正如文件中明确指出的:

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

  • 它必须包含无参数构造函数
  • 它应该只包含具有get和set访问权限的公共属性
  • 这些属性应仅为以下类型:
    • int、long、double、字符串、Guid、枚举值
换句话说,仅支持ValueType用作参数的成员

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

这一理念甚至有一个名字:

,正如该书明确指出的:

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

  • 它必须包含无参数构造函数
  • 它应该只包含具有get和set访问权限的公共属性
  • 这些属性应仅为以下类型:
    • int、long、double、字符串、Guid、枚举值
换句话说,仅支持ValueType用作参数的成员

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


这种哲学甚至有一个名字:

我可以在这里想到三种选择:

1) {Bad practice but easy}创建一个服务(mvvmcross中默认为singleton)来保存
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.Init()
上可以恢复数据

我建议将其用作一个简单的本地缓存,但您可以使用其他库或普通的SQLite表


3) 并将其作为字符串传递给
ShowViewModel()
init params。然后在Init()方法上反序列化它

我可以在这里想到3个选项:

1) {Bad practice but easy}创建一个服务(mvvmcross中默认为singleton)来保存
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.Init()
上可以恢复数据

我建议将其用作一个简单的本地缓存,但您可以使用其他库或普通的SQLite表


3) 并将其作为字符串传递给
ShowViewModel()
init params。然后在Init()方法上反序列化它

我没有看到对Init方法的任何调用…?
Init
方法在传递参数时会在mvvm模式中自动调用。如果我错了,请纠正我。请参考以下url,特别是在带参数的导航中-使用参数对象部分,我没有看到对Init方法的任何调用…?
Init
方法在传递参数时会在mvvm模式中自动调用。如果我错了,请纠正我。请参考以下url,特别是在带参数的导航中-使用参数对象部分,您有什么建议,我应该如何处理?将ObservableCollection转换为List然后传递它是否正确?我已经对你的答案投了赞成票。我建议不要依赖于框架的这些特性。viewmodels之间的导航非常容易自己构建,因此遵循了所有坚实的设计原则。您的viewmodels现在依赖于MVVMCross。这是相当可怕的,如果你以后想切换MVVM框架,即使我已经将ObservableCollection转换为列表,它仍然是nu