5

我正在关注Phil Haack在http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx上的信息

他谈到了非序列指数:

<form method="post" action="/Home/Create">

<input type="hidden" name="products.Index" value="cold" />
<input type="text" name="products[cold].Name" value="Beer" />
<input type="text" name="products[cold].Price" value="7.32" />

<input type="hidden" name="products.Index" value="123" />
<input type="text" name="products[123].Name" value="Chips" />
<input type="text" name="products[123].Price" value="2.23" />

<input type="hidden" name="products.Index" value="caliente" />
<input type="text" name="products[caliente].Name" value="Salsa" />
<input type="text" name="products[caliente].Price" value="1.23" />

<input type="submit" />
</form>

当您将模型绑定与 TextBoxFor 一起使用时,这在 MVC3 中是否可行?
这是使用顺序索引的方法:

@Html.TextBoxFor(m => m[i].Value)

如果不可能,如果我的索引不是连续的,我还能做些什么吗?

4

3 回答 3

1

AFAI 了解非顺序索引技术需要为每个索引值添加隐藏字段。我很确定 Html.TextBoxFor 助手本身不会生成任何额外的隐藏字段。可能您可以通过手动添加具有非顺序索引的隐藏字段来实现此目的。

于 2011-06-21T06:25:07.117 回答
0

我试过这个,但我无法让它与 textboxfor 一起工作。我使用了文本框并指定了名称。

<form method="post" action="/Home/Create">
@{var index = Guid.NewGuid();}
@Html.Textbox("products["+index +"].Name",Beer)
@Html.Textbox("products["+index +"].Price",7.32)
.
.
.
<input type="submit" />
</form>

您不需要 MVC 3.0 的隐藏索引。

让我知道如果这不起作用我有办法做到这一点,我只是从头顶上拿这个。

于 2011-07-11T15:14:11.317 回答
0

为了不弄乱您的视图,我发现这样做的最简单方法是遵循此扩展:BeginCollectionItem

完整的项目在这里:https ://github.com/danludwig/BeginCollectionItem

但是AFAIK你只需要这个类:

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;
            }
        }
    }

如何在您的视图中使用它:

<form method="post" action="/Home/Create">
    @foreach (var item in Model.Products) {    
        @using (Html.BeginCollectionItem("Products"))
        { 
            @Html.TextBoxFor(item => item.Name)
            @Html.TextBoxFor(item => item.Price)            
        }
     } 
         ...
         ...
</form>

我认为这比在你的视图中弄乱索引更干净......这是解释如何逐步做到这一点的帖子:http: //blog.stevensanderson.com/2010/01/28/editing-a-可变长度列表-aspnet-mvc-2-style/

Nuget 包: http ://www.nuget.org/packages/BeginCollectionItem/

于 2013-12-03T21:11:02.057 回答