MVVM ViewModel到模型通信和参数

时间:2016-04-28 14:26:27

标签: c# wpf mvvm model viewmodel

背景

我想我已经有了这个问题的答案,但是我尽可能地坚持MVVM,并且学习了很长时间。

我目前正在设置View,ViewModel和Model。我的模型使用实体框架查询数据库。

My View有一堆控件允许用户设置查询的参数(基本上构建一个大的where子句).ViewModel存储通过控件设置的这些选项。

所以我的观点 - 视图模型交互似乎非常有用,我认为它是可以接受的。

问题

我的模型公开了一个函数,它将查询结果作为某种IEnumerable返回。我现在遇到的问题是"搜索条件的数量"我已经设置了用户。我现在有模型功能的 9 参数。我不知道它是否可以接受。至少,它很难看。十分难看。但是这样,我的viewModel只需要保存模型的一个实例,然后只需要知道一个函数及其签名。

问题

我应该在模型中设置属性,然后在视图模型中设置这些属性吗?通过这种方式,单个功能将更加清晰,但视图模型必须更加“清晰”。该模型具有哪些属性。我知道创建一些公共属性并不是一件大事,但我想知道哪个更适合MVVM。我们当前的代码库没有任何关注点。所以我自己就这个。

问题代码

当前模型功能:

public IEnumerable<> GetResults(string id, string inputName, DateTime? fromDate,
    DateTime? toDate, bool option1, int selectCount, bool exactMatch = true, bool showFailed = false)
{
    //QUERY HERE, returns results
}

相关的ViewModel调用:

var queryResults = MyModel.GetResults(id, inputname, FromDate, ToDate, Option1, selectCount, ExactMatch, ShowFailed);
Results = queryResults.ToList();

建议的模型:

public string Id          {get;set}
public string InputName   {get;set}
public DateTime? FromDate {get;set}
public DateTime? ToDate   {get;set}
public bool Option1       {get;set}
public int SelectCount    {get;set}
public bool ExactMatch    {get;set}
public bool ShowFailed    {get;set}

public IEnumerable<> GetResults()
{
    //Query here, return results
}

相关提议的ViewModel调用:

MyModel.Id = this.Id;
MyModel.InputName = this.InputName;
MyModel.FromDate = this.FromDate;
//...etc (I put the this. to clarify the view model also has those properties).
var results= MyModel.GetResults();

2 个答案:

答案 0 :(得分:4)

据我了解,您的用例会因执行Command Query Separation而大喊大叫。关于CQS详细信息,您可以看到我的回答here。既然我们已将此作为我们想法的基础,我们将查看下一步的重构步骤。

重构参数泛滥

看到您的方法签名,我们可以清楚地看到您在这里有批次参数:

public IEnumerable<T> GetResults(string id, string inputName, DateTime? fromDate,
                                 DateTime? toDate, bool option1, int selectCount, 
                                 bool exactMatch = true, bool showFailed = false)

现在,如果我们引入parameter object而不是当前的九个参数,那么您的代码将变为如下:

public IEnumerable<T> GetResults(FilterObject filterObject)

看起来好多了吧?现在,示例参数对象只是POCO,如下所示:

public class FilterObject 
{
    public string id { get; set; }
    public string inputName { get; set; }
    ...
}

分离获得结果的担忧

分离关注点并摆脱紧密耦合的模型和视图模型。可以找到关于查询的非常好的简要介绍here。我们创建一个示例查询处理程序:

public class GetResultsQueryHandler
: IQueryHandler<FilterObject, YourModel>
{
    public GetResultsQueryHandler([pass your needed dependencies here])
    {
        //set them to local variables
    }

    public YourModel Handle(FilterObject filterObject)
    {
       // Logic to call GetResults(filterObject) and return the filled model
    }
}

现在,您可以很好地将之前的GetResults()调用分开,并让您的模型的属性为“已填充”。

将模型映射到视图模型

我们需要做的最后一件事是如何将模型映射到视图模型实例。那里有一堆对象映射器,一个流行的是AutoMapper。在像您这样的情况下,它可以让您的生活更轻松,您需要做的就是设置地图并致电Mapper.Map()

在您的问题中显示的示例中,模型和视图模型属性名称相同,映射定义应该很容易:

public static void Configure()
{
    Mapper.CreateMap<YourModel, YourViewModel>();
}

然后,为了获得结果映射视图模型,映射操作可以完成:

var viewModel = Mapper.Map<YourModel, YourViewModel>(model);

model参数是填充模型。

关于我的AutoMapper示例中显示的静态用例方法的引用:

  

AutoMapper的4.2.0版本将整个静态配置和映射API标记为过时的

这意味着使用AutoMapper&gt; = v4.2创建配置已更改为:

var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<YourModel, YourViewModel>();
});
var mapper = config.CreateMapper();

答案 1 :(得分:3)

我说,&#34;它取决于&#34;,这些参数的联系有多紧密。

它们可以分组,然后最好有多个功能。 例如按时间段,严重性,文本搜索等进行过滤。

当它们明显属于一起时,创建一个类或结构来对它们进行分组并传递一个参数。

考虑其他&#39;消费者&#39;可以/将来会使用您的模型,并根据/

做出决定