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 でこれは可能ですか?
これは、sequentiel インデックスでそれを行う方法です。

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

それが不可能な場合、インデックスが連続しない場合に他にできることはありますか?

4

3 に答える 3

1

非シーケンシャル インデックス手法では、インデックス値ごとに非表示フィールドを追加する必要があることを AFAI は理解しています。Html.TextBoxFor ヘルパー自体が追加の隠しフィールドを生成しないことは確かです。おそらく、非連続インデックスを持つ非表示フィールドを手動で追加することで、これを実現できます。

于 2011-06-21T06:25:07.117 に答える
0

これを試してみましたが、textboxfor で動作させることができませんでした。Textbox を使用して名前を指定しました。

<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

しかし、知る限り、このクラスだけが必要です:

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>

これは、ビューのインデックスをいじるよりもきれいだと思います...これを行う方法を段階的に説明する投稿は次のとおりです。可変長リスト aspnet-mvc-2-style/

Nuget パッケージ: http://www.nuget.org/packages/BeginCollectionItem/

于 2013-12-03T21:11:02.057 に答える