2012-03-04 52 views
1

我正在尋找一個關於單選按鈕和相關標籤的解決方案。我喜歡通過點擊相關標籤來選擇每個單選按鈕的方式。默認情況下,這不起作用。我的意思是標籤與單選按鈕沒有正確關聯。爲單選按鈕和相關標籤生成html標籤的自定義助手

例如:假設我們有一個名爲Revoked的屬性,其值可能是/否。我們希望使用單選按鈕讓用戶選擇值。

問題:當從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的世界仍然陌生,所以任何幫助都非常感謝。

謝謝。

回答

2

除此之外,可以作出輔助一些小的改進看起來不錯:

  • 你不需要使用相同的參數
  • 調用ModelMetadata.FromLambdaExpression兩次爲了生成你串接的ID屬性名稱與值,但此值可以包含任何字符,而HTML中的ID只允許某些字符。你需要清理它。
  • 您正在將value和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() 
    ); 
} 
+0

非常感謝你。這個版本更有效率。我有一個關於用IHtmlString替換MvcHtmlString的問題。有什麼不同? – Bronzato 2012-03-04 09:39:46

+0

@Bronzato,'MvcHtmlString'和'HtmlString'類實現了'IHtmlString'接口。在您的方法中始終暴露層次結構中最高級別的類/接口是一種很好的做法。在這種特殊情況下,在ASP.NET MVC 2中引入了'MvcHtmlString',以便與ASP.NET 4.0之前的.NET框架版本向後兼容。在ASP.NET MVC 3中,沒有更多理由使用它,因爲它需要ASP.NET 4.0。 – 2012-03-04 09:48:44

+0

你好我使用你的代碼..你可以幫助使用剃刀語法嗎?謝謝 – touinta 2018-01-10 08:31:27