【问题标题】:How to create a view model from a model interface in MVVM style?如何从 MVVM 样式的模型界面创建视图模型?
【发布时间】:2015-09-02 21:30:38
【问题描述】:

我使用的是视图模型优先方法,在某些模型中,我通过如下界面公开其他模型:

public class ModelA : IModel {}
public class ModelB : IModel {}
// plus yet unknown additional models

public class ViewModelA : IViewModel 
{
    ViewModelA(ModelA model){}
}
// a model may have several possible view models that should be selectable somehow
public class ViewModelAVariant : IViewModel 
{
    ViewModelAVariant(ModelA model){}
}
public class ViewModelB : IViewModel {}
{
    ViewModelA(ModelB model){}
}

public class ModelContainer
{
    public IModel[] SubModels { get { return new IModel { new ModelA(), new ModelB()};}}
}

public class ViewModelContainer
{
    private ModelContainer modelContainer;

    public IViewModel[] SubModels
    {
        get
        {
            return modelContainer.SubModels.Select( sm =>  ToViewModel(sm)).ToArray();
        }
    }


    private IViewModel ToViewModel(IModel model)
    {
        // what to insert here?
    }

}

可能的解决方案

变体 1:

存储IModelIViewModel 转换器的集合并在 ViewModel 中使用它们。

private IDictionary<type,Func<IModel,IViewModel>> converters;
private IViewModel ToViewModel(IModel model)
{
    return converters[model.GetType()](model);
}

优点:

  • 模型不必知道视图模型
  • 可以选择 ViewModels

缺点:

  • 如果没有合适的转换器,进程可能会在运行时失败

变体 2:

interface IModel
{
    IViewModel ToViewModel();
}

public class ModelA : IModel 
{
    // this enables view model selection
    public ModelA(Func<ModelA,IViewModel> converter)
    {
        this.converter = converter;
    }
    private Func<ModelA,IViewModel> converter;
    public IViewModel ToViewModel()
    {
        return converter(this);
    }
}

优点:

  • 可以选择 ViewModels
  • 易于使用,难以误用

缺点:

  • 模型必须了解视图模型

我正在寻找没有缺点的变体。

【问题讨论】:

  • 请问您为什么要这样做?视图模型应该知道它的模型,没有必要抽象它。而且一个模型不一定与单个视图模型相关,多个视图模型可能使用相同的模型...
  • “模型必须了解视图模型” 有一点是,遵循设计模式成为一种货物崇拜。我认为如果你担心这个,你应该开始用竹子制造飞机。
  • @almulo 我完全同意你的看法。视图模型应该知道它的模型。但我的问题是如何通过模型接口从模型创建视图模型,尤其是当有多个视图模型可供选择时。
  • 你...你不能? >_
  • 如果你从模型类型自动创建视图模型,很可能你最终得到的视图模型并没有真正做视图模型所做的任何事情(提供整个逻辑),而只是一个(无用的)包装器为模型。通常,您不想基于某些模型的选择来创建视图模型,而是希望显式地创建视图模型(因为您正在构建某些视图),此时视图模型可能会加载一个或多个模型。

标签: c# wpf mvvm model viewmodel


【解决方案1】:

听起来像是AutoMapper 的一个很好的用例。

基本上你会创建一个配置,最简单的情况是:

Mapper.CreateMap<ModelA, ViewModelA>();
Mapper.CreateMap<ModelA, ViewModelAVariant<>();
Mapper.CreateMap<ModelB, ViewModelB>();

这假定所有属性都命名相同(在 ViewModel 和 Model 中)。它还可以展平属性,即 ModelA.Property 被映射,按照约定,如果存在 ModelAProperty

如果您有更复杂的映射,则必须配置映射。

然后通过

解决
ModelA modelA = ... // retrieve ModelA 
ViewModelA viewModelA = Mapper.Map<ViewModelA>(modelA);

对于变体:

ModelA modelA = ... // retrieve ModelA 
ViewModelAVariation viewModelA = Mapper.Map<ModelA, ViewModelAVariation>(modelA);

您不应该以其他方式使用它,至少不建议从 ViewModel 转换为 Domain/Business Model。它的主要目标是模型到 DTO(数据传输对象)或模型到 ViewModel 的映射。

【讨论】:

  • 听起来像是变体2的全局方法。另一个问题是,当我检索ModelA时,我拥有的类型信息只有IModel
  • 您也可以使用Mapper.Map 的非通用版本,它接受Type 类型的参数,您可以通过modelA.GetType() 获得这些参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
相关资源
最近更新 更多