2013-09-27 3 views
1

Я все еще обертываю голову вокруг MVC, и я перешел из одного приложения модели в более сложное (многомодельное).Несколько моделей в 1 режиме?

Я создал свои модели в коде Первый способ, чтобы EF мог создать мою базу данных и таблицы для меня.

Скажем, у меня есть модель Человек, который имеет:

  • Имя
  • Телефон
  • Адрес
  • Город
  • StateId

Тогда у меня есть государство модель, имеет:

  • StateId
  • государственный

Я создал свой Контроллеры & Обзор для обоих этих моделей.

В моем лице Редактировать вид Я хотел бы отобразить комбинированное поле всех состояний, которые в настоящее время находятся в моей таблице состояний.

На мой взгляд, я вижу только:

@model IEnumerable<myProject.Models.Person> 

Я не вижу способ включить все государственные имена, так что я могу заполнить поле со списком.

Каков наилучший способ для этого?

+0

Самый быстрый способ разместить его в ViewBag и получить к нему доступ таким образом. –

ответ

4

Использование модели просмотра - это правильный путь. Затем вы можете создать частный метод на вашем контроллере, чтобы каждый раз создавать 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, чтобы предоставить текстовую метку для вашего StatesSelectList.

Перед тем, как попасть в здание список, давайте определим простой класс для хранения состояния:

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 в контроллере.

+1

Вау! Спасибо вам за этот отличный пост. Я ценю время, которое вы вложили в него, чтобы помочь мне понять это. У меня есть вопрос или два. Первый - это код контроллера. Это было для человека контролера? Если это так, у меня возникла проблема в Create Action, пытающаяся передать модель в db.Person.Add (модель) не работает. Мне нужен объект Person. Знаете ли вы, как я могу использовать ваш код для создания действия? – webdad3

+0

может это что-то вроде этого? db.Entry (model) .State = EntityState.Added; db.SaveChanges(); – webdad3

+0

@ webdad3 Добро пожаловать! По какой-то причине я испортил редактирование. На самом деле это был только стандартный «HomeController», с которым я тестировал. Что касается действия создания, вам нужно помнить, что тип модели, переданный этому действию, будет представлять собой модель представления, например «CreatePersonViewModel». Это означает, что вам нужно убедиться, что вы передаете 'model.Person' в Entity Framework, а не просто' model'. –

1

У вас есть как минимум 2 способа сделать это. Самый простой, «быстрый и грязный» способ - использовать ViewBag/ViewData/Session и хранить там список состояний. Одна (лучше ИМО) альтернатива заключается в создании ViewModel, который будет содержать Person, коллекцию государств и, возможно, какое государство было выбрано. Это будет выглядеть примерно так:

public class PersonViewModel 
{ 
    public Person Person { get; set; } 

    public State SelectedState { get; set; } 

    // this might also be IEnumerable<SelectListItem> depending on what you want to do. 
    public IEnumerable<State> States { get; set; } 
} 

Затем, в конструкторе, вызывать методы, которые заполняют ViewModel с данными. Привяжите ViewModel к вашему представлению и используйте его, как вы считаете нужным.

Смежные вопросы