2010-12-02 66 views
4

我创建了一个视图模型的ViewModels使用的SelectList设计Decison

public VMPosition 
{ 
     public VMPosition(){}//for model binder 
     public VMPosition(int EmployeeID) 
     { 
      PositionStatusList = new SelectList(_repo.getStatuses); 
      //populate other properties 
     } 
     public int CurrentPositionID { get; set; } 
     public int EmployeeID { get; set; } 
     public int CurrentPositionHistoryID { get; set; } 
     public bool AddingNew { get; set; } 
     public bool ClosingCurrent { get; set; } 
     public string CurrentPosition { get; set; } 
     public DateTime CurrentPositionStartDate { get; set; } 
     public string ReasonForDeparture { get; set; } 
     public SelectList PositionStatusList { get; set; } 

} 

我GET的ActionResult被定义为

public ActionResult UpdatePosition(int id) 
{ 
    return View(new VMPosition(id)); 
} 

我的帖子的ActionResult被定义为

public ActionResult UpdatePosition(int id, VMPosition Position) 
    { 
     if(ModelState.IsValid){ 
      Position Current = new Position{Position.Title etc..} 
      //save to db 
      return redirectToAction("someAction"); 
     } 
     return View(Position);//here is the problem 
    } 

我的SelectList填充在接受一个参数的构造函数中。如果模型状态无效,ModelBinder不能也不应该调用构造函数。我将不得不返回视图与模型对象(在这种情况下不包含SelectList值)。使用视图模型时如何处理这种情况。

我可以在actionresult中手动填充这些值,但这会违反DRY原则。然而,就这个问题而言,我想帮助解决更大的设计问题。

回答

2

在处理视图模型中的下拉菜单时,我通常只有一个属性与选定列表项的值相关联,而且我有一个属性返回selectlistitems列表。然后,我使用Html.DropDownListFor(m => m.ValueProperty,Model.DropDownValues)来呈现下拉菜单。

我想在你的情况下,你没有一个对应于所选listitem值的值?

编辑:下面是从我的应用程序的一个例子...

public class MyVM 
{ 
    public int MyObjectId { get; set; } 

    public List<SelectListItem> MyObjectList 
    { 
    get 
    { 
     List<SelectListItem> list = (from o in MyObjects select new SelectListItem 
     { Value = o.ObjectId.ToString(), Text = o.ObjectName }).ToList(); 
     list.Insert(0, new SelectListItem 
     { Value = "0", Text = "[Select an object]" }); 
     return list; 
    } 
    } 
} 

<%: Html.DropDownListFor(m => m.MyObjectId, Model.MyObjectList)%> 

你可能已经注意到了LINQ查询填充列表。在这个例子中,我有一个已经由AutoMapper填充的列表(MyObjects)。如果您愿意,您可以简单地返回一个静态列表。

+0

感谢您的快速回复。在get中编写列表代码是个不错的主意,但如果我们多次选择它,是否会导致两个单独的查询。我知道名单通常被称为查看一次,只是要求好奇! – 2010-12-02 13:11:57

+0

@穆罕默德:我相信你的问题的答案是,它取决于。在我的情况下,我有一个具有已经创建的子对象列表的实体。我使用AutoMapper将实体的数据复制到视图模型。当我查询视图模型的列表时,没有数据库交互性。但是,如果您依赖于IQueryable,则可能对列表进行查询可能导致数据库查询。同样的事情可以说,如果你通过直接访问仓库建立你的列表 - 在这种情况下,你可以使用视图模型的构造函数来填充本地列表一次? – Mayo 2010-12-02 13:16:48

10

为什么不按照我认为大多数人使用的惯例?您已将您的ViewModel与您的回购联系起来,我也建议更改回购。通过将repo.GetStatuses放入您的Controller/Action中很简单,它可以工作。我也更喜欢将SelectList放在我的视图中,并让ViewModel拥有物品清单 - 但这是我个人的偏好。然后,您可以清楚地看到/理解ViewModel处理的对象类型。 DRY是一个不是要求的原则。

视图模型

public VMPosition 
{ 
    public int StatusId { get; set; } 
    public IList<Status> StatusList { get; set; } 
} 

控制器

public ActionResult UpdatePosition(int id) 
{ 
    var model = new VMPosition(id); 
    model.StatusList = _repo.getStatuses; 
    return View(model); 
} 

public ActionResult UpdatePosition(int id, VMPosition Position) 
{ 
    if(!ModelState.IsValid) 
    { 
     Position.StatusList = _repo.getStatuses; 
     return View(Position); 
    } 
    ... 
} 

查看

<%= Html.DropDownListFor(m => m.StatusId, new SelectList(Model.StatusList)... 

编辑 - 重构PopulateSelectLists

public ActionResult UpdatePosition(int id) 
{ 
    var model = new VMPosition(id); 
    PopulateSelectLists(model); 
    return View(model); 
} 

public ActionResult UpdatePosition(int id, VMPosition Position) 
{ 
    if(!ModelState.IsValid) 
    { 
     PopulateSelectLists(Position); 
     return View(Position); 
    } 
    ... 
} 

private void PopulateSelectLists(VMPosition Position) 
{ 
    Position.StatusList = _repo.GetStatuses; 
    Position.OtherSelectList = ... 
    ... 
}