ViewModels с дизайном выбора SelectList - PullRequest
4 голосов
/ 02 декабря 2010

Я создал модель представления

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)); 
} 

Мой результат действия POST определен как

 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
    }

Мой список выбора равензаполняется в конструкторе, который принимает один параметр.Modelbinder не может и не должен вызывать конструктор, если состояние модели недопустимо.Мне придется вернуть View с моделью объекта (который в этом случае не содержит значение SelectList).Как можно справиться с этим сценарием при использовании моделей представления.

Я могу вручную заполнить эти значения в результате действия, но это нарушит принцип СУХОЙ.Однако для целей этого вопроса я хотел бы помочь с решением более крупного вопроса о дизайне.

Ответы [ 2 ]

10 голосов
/ 02 декабря 2010

Почему бы не следовать соглашению, которое, как я считаю, используют большинство людей? Вы связали свою ViewModel с репо, который я бы также рекомендовал изменить. Поместить repo.GetStatuses в ваш контроллер / действие просто и работает. Я также предпочитаю размещать SelectList внутри моего представления, и ViewModel содержит список элементов, но это мое личное предпочтение. Затем вы можете четко видеть / понимать, с какими типами объектов работает ваша ViewModel. СУХОЙ - это принцип, а не требование.

ViewModel

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);
    }
    ...
}

View

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

Правка - Refactor 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 = ...
    ...
}
2 голосов
/ 02 декабря 2010

При работе с раскрывающимися списками в моих моделях просмотра у меня обычно есть одно свойство, связанное со значением выбранного элемента списка, и у меня есть свойство, которое возвращает список элементов selectlist. Затем я использую Html.DropDownListFor (m => m.ValueProperty, Model.DropDownValues), чтобы отобразить раскрывающийся список.

Я полагаю, в вашем сценарии у вас нет значения, соответствующего значению выбранного элемента списка?

Редактировать: вот пример из одного из моих приложений ...

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, который заполняет список. В этом примере у меня есть список (MyObjects), который уже был заполнен AutoMapper. Вы можете просто вернуть статический список, если хотите.

...