Использование модели просмотра - это правильный путь. Затем вы можете создать частный метод на вашем контроллере, чтобы каждый раз создавать SelectList
. Такой подход не позволяет вам жертвовать безопасностью во время компиляции, которую вы бы сделали, если используете ViewBag
.
Так первый вверх, вид модель может выглядеть следующим образом:
public class EditPersonViewModel
{
public Person Person { get; set; }
[Display(Name = "State")]
public int StateId { get; set; }
public SelectList States { get; set; }
}
Причина, я имею StateId
свойства там, даже если бы мы могли получить доступ, что через Person
объекта, потому что в этом случае , Person
- это модель, и, на мой взгляд, я думаю, что нет смысла размещать аннотации данных на модели. В стороне, аннотация Display
просто позволяет вам контролировать, какой текст отображается при использовании LabelFor
, чтобы предоставить текстовую метку для вашего States
SelectList
.
Перед тем, как попасть в здание список, давайте определим простой класс для хранения состояния:
public class State
{
public int Id { get; set; }
public string Name { get; set; }
}
Далее, мы должны быть в состоянии построить SelectList
. Чтобы сделать это, вы можете добавить частный метод контроллера:
private SelectList GetStates(object selectedValue = null)
{
return new SelectList(this.States, StateListDataValueKey,
StateListDataTextKey, selectedValue);
}
this.States
представляет собой везде, где вы запрашиваете/хранить ваши данные о состоянии.Так что это может быть что-то вроде db.States.GetAll()
.
StateListDataValueKey
и StateListDataTextKey
представляют собой названия полей, которые вы хотите использовать в качестве выбранного значения и выбранного текста, соответственно. Таким образом, в этом случае StateListDataValueKey
должен быть Id
, а StateListDataTextKey
должен быть Name
. Я, как правило, определить их в мой контроллер:
public class HomeController : Controller
{
// rest of controller
// These two strings should correspond with
// the properties in your State class
private readonly string StateListDataValueKey = "Id";
private readonly string StateListDataTextKey = "Name";
}
Теперь мы можем перейти к созданию действий, чтобы отобразить данные для человека, а также для редактирования человека:
public ActionResult Edit(int id)
{
var model = new EditPersonViewModel();
// Get a person by Id.
model.Person = GetPerson(id);
// Call the utility method to build the list.
model.States = GetStates(model.Person.StateId);
return View(model);
}
[HttpPost]
public ActionResult Edit(EditPersonViewModel model)
{
if (ModelState.IsValid)
{
// Save the edits and then redirect.
return RedirectToActionPermanent("Index");
}
// Build the SelectList again so we can repopulate the view.
model.States = GetStates(model.Person.StateId);
return View(model);
}
сейчас это из пути, давайте посмотрим на соответствующую части представления редактирования:
@model EditPersonViewModel
<div class="editor-label">
@Html.LabelFor(model => model.StateId)
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.Person.StateId, Model.States)
@Html.ValidationMessageFor(model => model.States)
</div>
вызов LabelFor
использует аннотацию Display
данных, определенную ранее правильно Лаб l выпадающий список. В противном случае он будет помечен текстом «StateId», который не является полезным для ваших пользователей.
Update
Эти два частных поля, которые я указал в контроллере были пристанет мне немного, так как это не самый лучший способ делать вещи. Я оставил этот подход там, в случае, если вы предпочитаете его, но вот лучше реализация:
private SelectList BuildSelectList<TSource>(IEnumerable<TSource> source,
Expression<Func<TSource, int>> valueKey, Expression<Func<TSource, string>> textKey,
object selectedValue = null)
{
var selectedValueKey = ((MemberExpression)(MemberExpression)valueKey.Body).Member.Name;
var selectedTextKey = ((MemberExpression)(MemberExpression)textKey.Body).Member.Name;
return new SelectList(source, selectedValueKey, selectedTextKey, selectedValue);
}
Обратите внимания, как я сделал метод родовым, и я изменил название. Теперь вы можете использовать его для построения любого SelectList
, а не только для состояний. Вы можете использовать его так:
model.States = BuildSelectList(this.States, m => m.Id, m => m.Name, model.Person.StateId);
Вам больше не нужно определить StateListDataValueKey
или StateListDataTextKey
в контроллере.
Самый быстрый способ разместить его в ViewBag и получить к нему доступ таким образом. –