1

MVC2 テンプレートでは、通常this.ViewData.TemplateInfo.GetFullHtmlFieldId(fieldName) 、html 要素の id フィールドを生成するために使用します。これは、ほとんどの場合に機能しました。

ただし、このメソッドは実際には有効な id フィールドを返しません。プレフィックスfieldNameを付けるだけです。これは、HtmlFieldPrefix にViewData.TemplateInfo.HtmlFieldPrefixあるコレクションをレンダリングするときに問題を引き起こしています。[]

これらの文字を必要な場所に手動で変換してきまし_たが、これはエレガントではないようです (コードの繰り返し)。id フィールドを適切に生成する良い方法を見つけた人はいますか?

4

1 に答える 1

3

抱えている問題の種類について、より具体的に教えていただけますか?

たとえば、検証サポートが提供されている可変長リストを編集するエレガントなアプローチがあります。テンプレートを使用していませんが、部分ビューではまだ DRY のままです。

ID に一貫性がありませんが、名前は問題ありません。私が遭遇した唯一の問題は、jquery.infieldlabel を使用すると、ラベルの属性 (LabelFor ヘルパー内の GetFullHtmlFieldId によって生成される) が適切な TextBoxFor 入力の ID と一致しないように見えたことです。そこで、ID 生成に TextBox と同じメソッドを使用するだけの LabelForCollectionItem ヘルパー メソッドを作成しました。TagBuilder.GenerateId(fullName)

コードはあなたのニーズに対応していないかもしれませんが、私の問題の解決策を最初に探しているときにあなたの質問を見つけたので、誰かの助けになることを願っています.

public static class LabelExtensions
{
    /// <summary>
    /// Generates Label with "for" attribute corresponding to the id rendered by input (e.g. TextBoxFor), 
    /// for the case when input is a collection item (full name contains []).
    /// GetFullHtmlFieldId works incorrect inside Html.BeginCollectionItem due to brackets presense.
    /// This method copies TextBox's id generation.
    /// </summary>
    public static MvcHtmlString LabelForCollectionItem<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression,
               string labelText = null, object htmlAttributes = null) where TModel : class
    {
        var tag = new TagBuilder("label");
        tag.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // to convert an object into an IDictionary

        // set inner text
        string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
        string innerText = labelText ?? GetDefaultLabelText(html, expression, htmlFieldName);
        if (string.IsNullOrEmpty(innerText))
        {
            return MvcHtmlString.Empty;
        }
        tag.SetInnerText(innerText);

        // set for attribute
        string forId = GenerateTextBoxId(tag, html, htmlFieldName);
        tag.Attributes.Add("for", forId);

        return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
    }

    /// <summary>
    /// Extracted from System.Web.Mvc.Html.InputExtensions
    /// </summary>
    private static string GenerateTextBoxId<TModel>(TagBuilder tagBuilder, HtmlHelper<TModel> html, string htmlFieldName)
    {
        string fullName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName);
        tagBuilder.GenerateId(fullName);
        string forId = tagBuilder.Attributes["id"];
        tagBuilder.Attributes.Remove("id");
        return forId;
    }

    /// <summary>
    /// Extracted from System.Web.Mvc.Html.LabelExtensions
    /// </summary>
    private static string GetDefaultLabelText<TModel, TValue>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string htmlFieldName)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
        return labelText;
    }
}
于 2010-05-19T17:16:12.557 に答える