如何让我的编辑表格在ASP.NET MVC清单4财产剃刀对象 [英] How do I make an Edit Form for an object with a List property in ASP.NET MVC 4 with Razor

查看:119
本文介绍了如何让我的编辑表格在ASP.NET MVC清单4财产剃刀对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个编辑页面,我的MVC应用程序,使用剃刀。

I have an Edit page for my MVC application, using Razor.

我有一个像型号:

public class MyModelObject
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public List<MyOtherModelObject> OtherModelObjects { get; set; }
}

和MyOtherModelObject如下:

And MyOtherModelObject looks like:

public class MyOtherModelObject
{
    public string Name { get; set; }

    public string Description { get; set; }
}

我正在编辑页面MyModelObject。我需要一种方法来编辑页面上添加空间形式MyModelObject为用户创建/作为用户希望OtherModelObjects列表中添加尽可能多的MyOtherModelObject实例。

I am making Edit page for MyModelObject. I need a way to add space to the form on the Edit page for MyModelObject for the user to create/add as many MyOtherModelObject instances as the user wishes to the List of OtherModelObjects.

我想用户可以打一个按钮时,会做阿贾克斯(因为这是为了我的编辑页面的表单中的一部分,没有form标签),它返回表单元素的PartialView另一个动作。当用户添加了所有他们想要的MyOtherModelObjects和填写的数据,他们应该可以自己编辑保存到现有MyModelObject,这将HttpPost到编辑动作,并希望所有的MyOtherModelObjects将在正确的列表。

I'm thinking the user can hit a button, that will do ajax to another action which returns a PartialView of form elements (with no form tag since this is intended to part of the form on my edit page). When the user has added all the MyOtherModelObjects they want and filled out the data, they should be able to save their edits to the existing MyModelObject, that will HttpPost to the Edit action and hopefully all the MyOtherModelObjects will be in the correct list.

我还需要用户能够重新排序的项目,一旦他们加入他们。

I also need the user to be able to re-order the items once they've added them.

有谁知道如何使这项工作?有示例项目,或在线样本演练使用这一解决方案实现的?

Does anyone know how to make this work? Have sample project, or online sample walkthrough with this solution implemented?

推荐答案

这<一个href=\"http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/\">blog帖子包含了一步一步的指导,说明如何实现这一目标。

This blog post contains a step by step guide illustrating how to achieve that.

更新:

按照要求在评论部分,我说明如何一步一步适应上述条款,以您的方案。

As requested in the comments section I am illustrating step by step how to adapt the aforementioned article to your scenario.

型号:

public class MyOtherModelObject
{
    public string Name { get; set; }
    public string Description { get; set; }
}

public class MyModelObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<MyOtherModelObject> OtherModelObjects { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyModelObject
        {
            Id = 1,
            Name = "the model",
            Description = "some desc",
            OtherModelObjects = new[]
            {
                new MyOtherModelObject { Name = "foo", Description = "foo desc" },
                new MyOtherModelObject { Name = "bar", Description = "bar desc" },
            }.ToList()
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyModelObject model)
    {
        return Content("Thank you for submitting the form");
    }

    public ActionResult BlankEditorRow()
    {
        return PartialView("EditorRow", new MyOtherModelObject());
    }
}

查看(〜/查看/主页/ Index.cshtml

@model MyModelObject

@using(Html.BeginForm())
{
    @Html.HiddenFor(x => x.Id)
    <div>
        @Html.LabelFor(x => x.Name)
        @Html.EditorFor(x => x.Name)
    </div>
    <div>
        @Html.LabelFor(x => x.Description)
        @Html.TextBoxFor(x => x.Description)
    </div>
    <hr/>
    <div id="editorRows">
        @foreach (var item in Model.OtherModelObjects)
        {
            @Html.Partial("EditorRow", item);
        }
    </div>
    @Html.ActionLink("Add another...", "BlankEditorRow", null, new { id = "addItem" })

    <input type="submit" value="Finished" />
}

部分(〜/查看/主页/ EditorRow.cshtml

@model MyOtherModelObject

<div class="editorRow">
    @using (Html.BeginCollectionItem("OtherModelObjects"))
    {
        <div>
            @Html.LabelFor(x => x.Name)
            @Html.EditorFor(x => x.Name)
        </div>
        <div>
            @Html.LabelFor(x => x.Description)
            @Html.EditorFor(x => x.Description)
        </div>
        <a href="#" class="deleteRow">delete</a>
    }
</div>

脚本:

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

$('a.deleteRow').live('click', function () {
    $(this).parents('div.editorRow:first').remove();
    return false;
});


备注:在 BeginCollectionItem 自定义的助手是从我已经联系到同一篇文章拍摄,但我在这里向它提供答案的完整性起见:


Remark: the BeginCollectionItem custom helper is taken from the same article I've linked to, but I am providing it here for completeness sake of the answer:

public static class HtmlPrefixScopeExtensions
{
    private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";

    public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
    {
        var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
        string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();

        // autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
        html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));

        return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
    }

    public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
    {
        return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
    }

    private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
    {
        // We need to use the same sequence of IDs following a server-side validation failure,  
        // otherwise the framework won't render the validation error messages next to each item.
        string key = idsToReuseKey + collectionName;
        var queue = (Queue<string>)httpContext.Items[key];
        if (queue == null)
        {
            httpContext.Items[key] = queue = new Queue<string>();
            var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
            if (!string.IsNullOrEmpty(previouslyUsedIds))
                foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
                    queue.Enqueue(previouslyUsedId);
        }
        return queue;
    }

    private class HtmlFieldPrefixScope : IDisposable
    {
        private readonly TemplateInfo templateInfo;
        private readonly string previousHtmlFieldPrefix;

        public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
        {
            this.templateInfo = templateInfo;

            previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
            templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
        }

        public void Dispose()
        {
            templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
        }
    }
}

这篇关于如何让我的编辑表格在ASP.NET MVC清单4财产剃刀对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆