ASP.NET MVC: Коллекция в модели, как заполнять?

492
25 апреля 2017, 05:06

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

Пытался делать по гайду http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

Сейчас вместо добавления поля ввода кидает на отдельную страницу с этим полем ввода

Checklist.cs - моя модель

public class Checklist
{
    public int Id { get; set; }
    public string Identifier { get; set; }
    public IEnumerable<Checks> CheckList { get; set; }
    public DateTime Date { get; set; }
}
public class Checks
{
    public int Id { get; set; }
    public string Check { get; set; }
}

Create.cshtml

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <h4 align="right">New Checklist</h4>
    @Html.TextBoxFor(model => model.Identifier, new { @class = "form-control", @maxlength = "15", @style = "width:280px" })
    @Html.ValidationMessageFor(model => model.Identifier, "", new { @class = "text-danger" })
    @Html.TextBoxFor(model => model.Title, new { @class = "form-control", @maxlength = "255" })
    @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })

    <table id="Table">
        <tr>
            <th>Checks</th>
        </tr>
        <tr>
            <td id="editorRows">
                @if (Model.CheckList != null)
                {
                    foreach (var item in Model.CheckList)
                    {
                        @Html.Partial("_create_check", item);
                    }
                }
            </td>
        </tr>
    </table>
    @Html.ActionLink("Add", "BlankEditorRow", null, new { id = "addItem" })
    <input type="submit" value="Create" class="btn btn-primary" />
    }

add-check.js

$('#addItem').click(function () {
    $.ajax({
        url: this.href,
        cache: false,
        success: function (html) { $("#editorRows").append(html); }
    });
    return false;
});

_create_check - частичное представление

@model MyProject.Models.Checks
@using (Html.BeginCollectionItem("checks")) { 
    @Html.HiddenFor(model => model.Id)
    @Html.TextBoxFor(model => model.Check, new { @class = "form-control" })
}

ChecklistsController.cs

public ViewResult BlankEditorRow()
{
    return View("_create_check", new Checks());
}
public ActionResult Create()
{
    Checklist checks = new Checklist();
    return View(checks);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Identifier,Title,Date,CheckList")] Checklist checklist)
{
    if (ModelState.IsValid)
    {
        checklist.Date = DateTime.Now;
        db.Checklists.Add(checklist);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(checklist);
}
Answer 1

Я бы вам посоветовал сделать отображение PartialView по кнопке и его скрытие по другой кнопке. Приведу пример:

<div id="partialBlankEditor" style="display : none;">
   @Html.Partial("BlankEditorRow", Model.LiftItems.Where(x => x.IsDeleted).ToList())
</div>

Так как метод BlankEditorRow возвращает частичное представление, то у нас после загрузки страницы сразу отобразится частичное представление. Для скрытия и отображения можно использовать у div свойство display: none;, на основное представление добавить кнопку по нажатию на которую будем у partialBlankEditor менять свой свойство на display: block; к примеру. Вот таким кодом:

$('#partialBlankEditor').style.display = 'block';

Навесим это к примеру на кнопку вместо этого:

@Html.ActionLink("Add", "BlankEditorRow", null, new { id = "addItem" })

сделаем просто кнопку с идентификатором:

<button type="button" id="btn-show-editor">Show add</button>

Ну и обработка будет такой:

$('#btn-show-editor').click(function () {
    $('#partialBlankEditor').style.display = 'block';
});

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

@model MyProject.Models.Checks
@using (Html.BeginCollectionItem("checks")) { 
    @Html.HiddenFor(model => model.Id)
    @Html.TextBoxFor(model => model.Check, new { @class = "form-control" })
    <button type="button" id="btn-add-new-item">Add new</button>
}

Обработку нажатия кнопки сделаем тоже простой, скрываем частичное представление и вызываем метод Ajax:

$('#btn-add-new-item').click(function () {
    $.ajax({
        url: 'CreateNew',
        cache: false,
        data: {id: '@Model.Id', check: '@Model.Check'}
        success: function (response) { 
          // $("#editorRows").append(response); немного иначе нужно сделать перерисовку
        }
    });
    return false;
});

Нужно написать новый метод, с помощью которого будем добавлять новое значение и возвращать новый список, причем нужно будет отправить данные в Data с помощью Ajax из @using(Html.BeginCollectionItem("checks")). Я не пользовался BeginCollectionItem, поэтому посоветую старый добрый @using(Ajax.BeginForm позволяющий обновить часть страницы без перезагрузки ее целиком.

Новый метод как-то так будет выглядеть:

// имена должны совпасть с данными из Ajax 
public ActionResult CreateNew(int id, string check)
{
    Checks newData = new Checks() { Id = id, Check = check };
    // куда-то добавляем наш чек, в БД к примеру
    // получаем идентификатор, так как он будет нулевым, так как объект новый
    // newLst - это новый набор данных из IEnumerable<Checks>
    // можно сериализовать через JavaScriptSerializer newLst
    return Json(newLst);
}

Вот этот блок кода вызывает вопросы и сомнения:

<td id="editorRows">
    @if (Model.CheckList != null)
    {
        foreach (var item in Model.CheckList)
        {
            @Html.Partial("_create_check", item);
        }
    }
</td>

Вот он немного не ясен, возможно Вы тут хотели что-то отобразить в виде списка к примеру? Но тут наверняка не нужно отображать частичное представление добавления новых. Во-первых, у вас в модели CheckList будет пустой коллекцией и не отобразится ни одного элемента. В общем, перепишите этот блок кода, то что находится внутри цикла foreach, чтобы потом аяксом можно было обновить список, к примеру сделать через select и option, его будет просто перерисовать через Ajax

READ ALSO
Запутался с флагами, ARM

Запутался с флагами, ARM

Доброго времени сутокЧто-то я уже мозг сломал

203
Написать условие

Написать условие

Есть простая строка string stroka="qwertyuioplkjhgfdsazxcvbm";//случайный набор символов далее

248
EXE Приложение на сервер

EXE Приложение на сервер

Можно ли установить winforms (C#) приложение на сервер что бы при переходе по ссылке пользователь не скачивал исполняемый файл а именно начинал...

252
Непонятный результат вычисления

Непонятный результат вычисления

Почему в данном случае a будет равно 20, а не 21?

191