13

我的 MVC 应用程序具有经典的父子(主从)关系。

我想要一个页面,在同一页面上创建新的父级和子级。我添加了一个返回部分视图并将子 HTML 添加到父视图的操作,但我不知道如何将操作中新创建的子级关联到原始父级(换句话说,我如何添加新的子实体到父实体中这些实体的集合)。

我想当我提交表单时,该操作应该在其集合中获取包含新创建子项的父实体。

所以简而言之,创建子实体的操作代码应该是什么,以及如何将子实体添加到其父集合中?

我在这里(和其他网站)阅读了很多帖子,但找不到示例。

该应用程序使用 MVC 4 和 Entity Framework 5。

代码示例(我删除了一些代码以保持简单)。该模型是 Form(父)和 FormField(子)实体。

public partial class Form
{ 
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<FormField> FormFields { get; set; }
}

public partial class FormField
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int FormID { get; set; }
}

以下部分视图 (_CreateFormField.cshtml) 创建新的 FormField(子)。

@model FormField

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>FormField</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.FormID)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.FormID)
        @Html.ValidationMessageFor(model => model.FormID)
    </div>


</fieldset>
}

以下视图 (Create.cshtml) 是创建表单的视图。

@model Form

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>Form</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>

<div>
        @Html.ActionLink(
                "Add Field",
                "CreateFormField", 
                new { id = -1},
                new { @class = "form-field" })
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

<div id="CreateFormField"></div>

@section Scripts {
<script>
    $(function () {
        $('.form-field').on('click', function (e) {

            $.get($(this).prop('href'), function (response) {
                $('#CreateFormField').append(response)
            });

            e.preventDefault();
        });
    });
</script>

@Scripts.Render("~/bundles/jqueryval")

}

以下操作处理 FormController 中的创建。

[HttpPost]
public ActionResult Create(Form form)
{
    if (ModelState.IsValid)
    {
        db.Forms.Add(form);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(form);
}

public ActionResult CreateFormField(string id = null)
{
    // I guess something is missing here.

    return PartialView("_CreateFormField", new FormField());
}

提前致谢,

沙龙。

4

5 回答 5

1

您可以在父 cshtml 页面中使用 @Html.RenderPartial(_CreateFormField.cshtml) htlper 方法。

有关模式信息, http: //msdn.microsoft.com/en-us/library/dd492962 (v=vs.118).aspx

我提供了一个伪代码示例,

@Foreach(childModel in model.FormFields)
{
    @Html.RenderPartial("childView.cshtml","Name", childModel)
}

请以正确的 c# 语法方式尝试它,您将获得为每个集合项呈现的部分视图。

于 2014-12-15T12:41:21.270 回答
1

我认为对你来说最好和最简单的方法是你有一个创建视图,Form并在它的底部放置一个fieldset分配FormFields给它。

对于字段集,您应该有两个局部视图:一个用于创建,另一个用于编辑。创建的局部视图应该是这样的:

@model myPrj.Models.Form_FormFieldInfo

@{ 
    var index = Guid.NewGuid().ToString(); 
    string ln = (string)ViewBag.ListName;
    string hn = ln + ".Index";
}

<tr>
    <td>        
        <input type="hidden" name="@hn" value="@index" />
        @Html.LabelFor(model => model.FormFieldID)
    </td>
    <td>
        @Html.DropDownList(ln + "[" + index + "].FormFieldID", 
            new SelectList(new myPrj.Models.DbContext().FormFields, "ID", "FieldName"))
    </td>        
    <td>
        <input type="button" onclick="$(this).parent().parent().remove();" 
            value="Remove" />
    </td>
</tr>

通过 ajaxly 在 create place view 中调用这个局部视图,您可以为每个标签呈现一些元素。每行元素都包含一个标签、一个包含标签的 DropDownList 和一个删除按钮,用于简单地删除创建的元素。

在创建地点视图中,您有一个裸表,其中包含您通过部分视图创建的那些元素:

<fieldset>
     <legend>Form and FormFields</legend>
     @Html.ValidationMessageFor(model => model.FormFields)</label>
     <table id="tblFields"></table>                                        
     <input type="button" id="btnAddTag" value="Add new Field"/>
     <img id="imgSpinnerl" src="~/Images/indicator-blue.gif" style="display:none;" />
</fieldset>

并且您有以下脚本来为每个标签创建一行元素:

$(document).ready(function () {
    $("#btnAddField").click(function () {
        $.ajax({
            url: "/Controller/GetFormFieldRow/FormFields",
            type: 'GET', dataType: 'json',
            success: function (data, textStatus, jqXHR) {
                $("#tblFields").append(jqXHR.responseText);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                $("#tblFields").append(jqXHR.responseText);
            },
            beforeSend: function () { $("#imgSpinnerl").show(); },
            complete: function () { $("#imgSpinnerl").hide(); }
        });
    });
});

动作方法GetFormFieldRow如下:

public PartialViewResult GetFormFieldRow(string id = "")
    {            
        ViewBag.ListName = id;
        return PartialView("_FormFieldPartial");
    }

并且您已完成创建...您问题的整个解决方案有许多用于视图、部分视图、控制器、ajax 调用和模型绑定的代码。我试图向您展示方式,因为我真的无法在此答案中发布所有这些。

是完整的信息和操作方法。

希望这个答案对您有用并为您指明方向。

于 2013-07-27T12:42:24.970 回答
0

问题是您的局部视图需要使用:

@model Form //Instead of FormField

然后在局部视图内部,您必须使用模型 => 模型。表单域 .x

<div class="editor-label">
    @Html.LabelFor(model => model.FormField.Name)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.FormField.Name)
    @Html.ValidationMessageFor(model => model.FormField.Name)
</div>

这仅适用于一对一的关系(或者我在这个线程中读到:这里)。部分视图中是否有 @Html.Form 也没关系。

进行这些更改后,我可以毫无问题地将所有发布的数据返回到控制器。

编辑:我遇到了这个问题,因为任何人都会很快发现。

更好的方法(我已经看到)是使用 EditorTemplate。这样编辑器就保持独立于父级,您可以在任何页面上添加表单,而不仅仅是在其中添加 FormField 的页面。

然后你会替换

@Html.Partial("view")

@Html.EditorFor()

基本上,我发现在进行编辑时使用 @Html.EditorFor 而不是局部视图要好得多(它称为视图 - 不是编辑器)。

于 2013-06-06T17:22:21.970 回答
0

如果您想使用基于网格的布局,您可能想尝试Kendo UI 网格

于 2015-01-07T16:49:58.517 回答
0

使用 jQuery 在单击按钮时添加 FormField。

类似的我使用它如下

 <div class="accomp-multi-field-wrapper">
 <table class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>FormId</th>
            <th>Remove</th>
           </tr>
     </thead>
<tbody class="accomp-multi-fields">
 <tr class="multi-field">
        <td> <input name="FormFields[0].Name" type="text" value=""></td>
        <td> <input name="FormFields[0].FormId" type="text" value=""></td>
        <td> <button type="button" class="remove-field">X</button></td>
     </tr> 

</tbody>
<tr>
    <th><button type="button" class="add-field btn btn-xs btn-primary addclr"><i class="fa fa-plus"></i> Add field</button> </th>
</tr>
</table>
</div>

和jQuery如下添加字段和删除

 <script>
 $('.accomp-multi-field-wrapper').each(function () {
          var $wrapper = $('.accomp-multi-fields', this);
          $(".add-field", $(this)).click(function (e) {
          var $len = $('.multi-field', $wrapper).length;
          $('.multi-field:first-child', $wrapper).clone(false, true).appendTo($wrapper).find('select,input,span').val('').each(function () {
          $(this).attr('name', $(this).attr('name').replace('\[0\]', '\[' + $len + '\]'));
    });

$(document).on("click",'.multi-field .remove-field', function () {
            if ($('.multi-field', $wrapper).length > 1) {
                $(this).closest('tr').remove();
                //
                $('.multi-field', $wrapper).each(function (indx) {
                    $(this).find('input,select,span').each(function () {
                      $(this).attr('name', $(this).attr('name').replace(/\d+/g, indx));

                    })
                })
            }
        });
    </script>

希望这会对你有所帮助。

于 2015-02-07T11:38:24.973 回答