2012-03-04 2 views
1

ラジオボタンと関連するラベルについてのソリューションを探していました。私は、関連するラベルをクリックして各ラジオボタンを選択できるようにしています。デフォルトでは、これはうまく動作しません。私は、ラベルがラジオボタンと正しく関連付けられていないことを意味します。ラジオボタンと関連ラベルのhtmlタグを生成するためのカスタムヘルパー

例:可能性のある値Yes/Noを持つRevokedという名前のプロパティがあるとします。ラジオボタンを使用してユーザーが値を選択できるようにしたいと考えています。

問題: MVC(Html.LabelFor、Html.RadioButtonFor)からhtmlタグを生成した場合、両方のラジオボタンのID(Yes/No)は同じです。したがって、各ラベルを対応するラジオボタンに関連付けることは不可能である。

解決策:私は正しい独自の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

は正常に見える:

  • あなたが連結されているIDを生成するために同じ引数
  • で二回ModelMetadata.FromLambdaExpressionを呼び出す必要はありませんproperty nameには値を指定しますが、この値には任意の文字を含めることができますが、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

はどうもありがとうございました。このバージョンははるかに効率的です。私はMvcHtmlStringをIHtmlStringに置き換えることに関して1つの質問があります。違いはなんですか? – Bronzato

+0

@Bronzatoでは、 'MvcHtmlString'クラスと' HtmlString'クラスの両方が 'IHtmlString'インターフェースを実装しています。メソッドの階層内で可能な限り高いクラス/インタフェースを常に公開することをお勧めします。この特別な場合、 'MvcHtmlString'がASP.NET MVC 2に導入され、ASP.NET 4.0より前のバージョンの.NETフレームワークとの下位互換性が確保されています。 ASP.NET MVC 3では、ASP.NET 4.0が必要なので、これを使用する必要はもうありません。 –

+0

こんにちは私はあなたのコードを使用しました。剃刀の構文を助けてもらえますか?ありがとう – touinta

関連する問題