1

在 MVC2 模板中,我通常用于this.ViewData.TemplateInfo.GetFullHtmlFieldId(fieldName) 生成 html 元素的 id 字段。这在大多数情况下都有效。

但是,此方法实际上并没有返回有效的 id 字段,它只是以 为前缀fieldNameViewData.TemplateInfo.HtmlFieldPrefix这在呈现[]HtmlFieldPrefix 中的集合时给我带来了问题。

我一直在手动将这些字符转换到_我认为需要的位置,但这似乎并不优雅(重复代码),有没有人找到正确生成 id 字段的好方法?

4

1 回答 1

3

您能否更具体地说明您遇到的问题类型?

例如,有一种优雅的方法来编辑可变长度列表并提供验证支持。虽然它不使用模板,但部分视图仍然保持 DRY。

虽然 id 不一致 - 名称没问题,我遇到的唯一问题是使用 jquery.infieldlabel 似乎标签的 for 属性(由 LabelFor 助手中的 GetFullHtmlFieldId 生成)与相应 TextBoxFor 输入的 id 不匹配。所以我创建了 LabelForCollectionItem 辅助方法,它使用与 TextBox 相同的方法生成 id -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 回答