MVC: редактор для списка данных

#c# #asp.net #asp.net-mvc

#c# #asp.net #asp.net-mvc

Вопрос:

Я хочу сделать что-то похожее на то, что объясняется в этом вопросе: я хочу отредактировать список данных.

Разница в том, что база не является списком.

(Я использую VS 2013, так что это не старый материал.)

Моя модель представления:

 public class SampleViewModel
{
    // ... other properties for editing ...

    // The list property
    public List<SampleListItemViewModel> ItemList { get; set; }
}

public class SampleListItemViewModel
{
    // For display only. It has an ID field to identify the row.
    public MyEntity Item { get; set; }

    // I want to modify this!
    public bool IsChecked { get; set; }
}
  

Моя попытка просмотра:

 @model My.Namespace.SampleViewModel

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <!-- ... normal editing, MVC generated ... -->

    <!-- BEGIN LIST EDIT -->

    <table>
        <tr>
            <th>
                Is Applicable
            </th>
            <!-- ... -->
        </tr>

        @foreach (var doc in Model.ItemList)
        {
            @Html.HiddenFor(modelItem => doc.Document.CRMDocumentId)

            <tr>
                <td>
                    @Html.EditorFor(modelItem => doc.IsChecked)
                    <!-- @Html.ValidationMessageFor(modelItem => doc.IsChecked) -->
                </td>
                <!-- ... other non-editable display fields, e.g. name ... -->
            </tr>
        }

    <!-- END LIST EDIT -->

    <!-- ... -->

}
  

Когда я создаю представление, оно показывает все так, как я хочу, но когда я нажимаю «Создать», список элементов равен нулю.

РЕДАКТИРОВАТЬ — Дополнительная информация

Контроллер:

     public ActionResult Create(int? id)
    {
        var item = // ...populate...
        // I confirmed that ItemList has values.
        return View(item);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(SampleViewModel item)
    {
        // This is null
        var list = item.ItemList;

        // ignoring all else for now

        return View(item);
    }
  

Комментарии:

1. Что вы делаете, когда нажимаете на ссылку «Создать»?? Не могли бы вы показать нам код??

2. Хорошо, можешь попробовать это — создай конструктор SampleViewModel и инициализируй свойство ItemList следующим образом — ItemList = new List<SampleListItemViewModel>() в конструкторе, а затем проверь…

3. Я пока мало что делаю в контроллере, но я обновил свой вопрос. Я подтвердил, что список элементов имеет значения.

Ответ №1:

Чтобы связать сложные объекты, нам нужно предоставить индекс для каждого элемента, а не полагаться на порядок элементов. Это гарантирует, что мы сможем однозначно сопоставить представленные свойства с правильным объектом.

Замените foreach цикл на for loop:

 @for (int i=0; i<Model.ItemList.Count; i  )
    {
        @Html.HiddenFor(modelItem => modelItem.ItemList[i].Document.CRMDocumentId)

        <tr>
            <td>
                @Html.EditorFor(modelItem => modelItem.ItemList[i].IsChecked)
                @Html.ValidationMessageFor(modelItem => modelItem.ItemList[i].IsChecked)
            </td>

        </tr>
    }
  

ПРИМЕЧАНИЕ:

Обратите внимание, что индекс должен представлять собой непрерывную последовательность целых чисел, начинающихся с 0 и увеличивающихся на 1 для каждого элемента

Также для каждого свойства в списке, которое вы не хотите, чтобы пользователь редактировал, например, идентификатор пользователя и т.д., Добавьте @Html.HiddenFor(..) для этого свойства, иначе оно будет отправлено null на сервер, и если для них создано скрытое поле, их не будет NULL .

Более подробную информацию вы можете увидеть ЗДЕСЬ

Также см. Привязку модели к списку

Комментарии:

1. Спасибо! Кроме того, для каждого @Html.DisplayFor(..) в списке также добавьте @Html.HiddenFor(..) , потому что тогда ASP отправит данные только для просмотра обратно на сервер, и они не будут равны нулю, если страница перезагрузится с ошибками проверки.

2. @PeetBrits да, если вы не создадите скрытое поле для объекта модели, который вы не показываете в представлении, оно будет опубликовано с нулевым значением