自定义帮助程序,用于为单选按钮和关联标签生成html标记

时间:2012-03-04 08:21:49

标签: asp.net asp.net-mvc

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

示例:假设我们有一个名为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世界的新手,所以非常感谢任何帮助。

感谢。

1 个答案:

答案 0 :(得分:2)

除了可以做出的一些小改进之外,帮助者看起来很好:

  • 您无需使用相同的参数
  • 两次调用ModelMetadata.FromLambdaExpression
  • 为了生成id,您将属性名称与值连接,但此值可以包含任何字符,而HTML中的id仅允许某些字符。你需要消毒它。
  • 您正在将值和currentValue同时转换为字符串,如果在其他某些属性类型上使用了帮助程序,则可能会失败。在这种情况下,通过反映帮助程序签名或使用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()
    );
}