2010-12-02 64 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 = ... 
    ... 
}