【问题标题】:Custom helper for generating html tags for radio button and associated label用于为单选按钮和相关标签生成 html 标签的自定义助手
【发布时间】:2012-03-04 08:21:49
【问题描述】:

我正在寻找有关单选按钮和相关标签的解决方案。我喜欢我们可以通过单击相关标签来选择每个单选按钮的方式。默认情况下,这不是很好。我的意思是标签与单选按钮没有正确关联。

示例:假设我们有一个名为 Revoked 的属性,其可能值为 Yes/No。我们想使用单选按钮让用户选择值。

问题:当从MVC(Html.LabelFor,Html.RadioButtonFor)生成html标签时,两个单选按钮的ID(是/否)是相同的。因此不可能将每个标签与相应的单选按钮相关联。

解决方案:我创建了自己的自定义助手,用于生成具有正确且唯一 ID 的 html 标签。

这是我的助手:

    public static MvcHtmlString RadioButtonWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object labelText)
    {
        object currentValue = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model;
        string property = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).PropertyName;

        // Build the radio button html tag
        TagBuilder htmlRadio = new TagBuilder("input");
        htmlRadio.MergeAttribute("type", "radio");
        htmlRadio.MergeAttribute("id", property + value);
        htmlRadio.MergeAttribute("name", property);
        htmlRadio.MergeAttribute("value", (string)value);

        if (currentValue != null && value.ToString() == currentValue.ToString()) htmlRadio.MergeAttribute("checked", "checked");

        // Build the label html tag
        TagBuilder htmlLabel = new TagBuilder("label");
        htmlLabel.MergeAttribute("for", property + value);
        htmlLabel.SetInnerText((string)labelText);

        // Return the concatenation of both tags
        return MvcHtmlString.Create(htmlRadio.ToString(TagRenderMode.SelfClosing) + htmlLabel.ToString());
    }

它有效,但我需要建议。你怎么看?它有效率吗?我对 ASP.NET MVC 的世界还很陌生,因此非常感谢任何帮助。

谢谢。

【问题讨论】:

    标签: asp.net asp.net-mvc


    【解决方案1】:

    除了可以使助手看起来不错的一些小改进之外:

    • 您无需使用相同的参数调用两次ModelMetadata.FromLambdaExpression
    • 为了生成 id,您将属性名称与值连接起来,但该值可以包含任何字符,而 HTML 中的 id 只允许某些字符。您需要对其进行消毒。
    • 您正在将 value 和 currentValue 都转换为字符串,如果在其他属性类型上使用 helper,这可能会失败。在这种情况下,要么通过反映助手签名使助手仅使用字符串属性,要么使用Convert.ToString()

    这是考虑到这些评论的重构版本:

    public static IHtmlString RadioButtonWithLabelFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        TProperty value, 
        string labelText
    )
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        object currentValue = metadata.Model;
        string property = metadata.PropertyName;
    
        // Build the radio button html tag
        var htmlRadio = new TagBuilder("input");
        htmlRadio.GenerateId(property + value);
        htmlRadio.Attributes["type"] = "radio";
        htmlRadio.Attributes["name"] = property;
        htmlRadio.Attributes["value"] = Convert.ToString(value);
    
        if (object.Equals(currentValue, value))
        {
            htmlRadio.Attributes["checked"] = "checked";
        }
    
        // Build the label html tag
        var label = new TagBuilder("label");
        label.Attributes["for"] = htmlRadio.Attributes["id"];
        label.SetInnerText(labelText);
    
        // Return the concatenation of both tags
        return new HtmlString(
            htmlRadio.ToString(TagRenderMode.SelfClosing) + label.ToString()
        );
    }
    

    【讨论】:

    • 非常感谢。这个版本效率更高。我有一个关于用 IHtmlString 替换 MvcHtmlString 的问题。有什么区别?
    • @Bronzato,MvcHtmlStringHtmlString 类都实现了 IHtmlString 接口。始终在方法的层次结构中公开可能最高的类/接口是一种很好的做法。在这种特殊情况下,MvcHtmlString 是在 ASP.NET MVC 2 中引入的,用于向后兼容 ASP.NET 4.0 之前的 .NET 框架版本。在 ASP.NET MVC 3 中没有更多理由使用它,因为它需要 ASP.NET 4.0。
    • 您好,我使用了您的代码..您可以帮助使用剃刀语法吗?谢谢
    • 能否举例说明如何在剃须刀页面中使用自定义助手? @DarinDimitrov
    猜你喜欢
    • 2019-11-07
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 2021-08-05
    • 2012-10-27
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多