web-dev-qa-db-ja.com

強く型付けされたRadioButtonlist

いくつかのオプション(支払い方法の現金、クレジットカードなど)を取得して、これらをラジオボタンにバインドしたいと思います。 MVC3にはRadioButtonListはないと思います。

また、ラジオがバインドされたら、回答を編集しているときに、以前に選択したオプションをユーザーに表示したいと思います。

19
Vivek

いつものように、モデルから始めます。

public enum PaiementMethod
{
    Cash,
    CreditCard,
}

public class MyViewModel
{
    public PaiementMethod PaiementMethod { get; set; }
}

次にコントローラー:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

そして最後にビュー:

@model MyViewModel
@using (Html.BeginForm())
{
    <label for="paiement_cash">Cash</label>
    @Html.RadioButtonFor(x => x.PaiementMethod, "Cash", new { id = "paiement_cash" })

    <label for="paiement_cc">Credit card</label>
    @Html.RadioButtonFor(x => x.PaiementMethod, "CreditCard", new { id = "paiement_cc" })

    <input type="submit" value="OK" />
}

そして、これをヘルパーにカプセル化するより一般的なソリューションが必要な場合は、 次の回答 が役立つ場合があります。

37
Darin Dimitrov

これが私がRadioButtonListsをバインドする方法です。ビューモデルには、強く型付けされたオブジェクトのコレクションがあります。たとえば、PaymentOptionsはコードテーブルである可能性があります。コレクションとともに、SelectedPaymentOptionKey(または主キーの前にIdを付ける場合はSelected * Id)があります。最初、このキーはデフォルトで0になりますが、ポストバックでは、選択したアイテムの値を保持します。

public class PaymentSelectionVM
{
  public ICollection<PaymentOption> PaymentOptions { get; set; }
  public int SelectedPaymentOptionKey { get; set; }
}

public ViewResult PaymentSelection()
{
  var paymentOptions = db.PaymentOptions.ToList();
  return View(
    new PaymentSelectionVM { 
      PaymentOptions = paymentOptions,

      //This is not required, but shows how to default the selected radiobutton
      //Perhaps you have a relationship between a Customer and PaymentOption already,
      //SelectedPaymentOptionKey = someCustomer.LastPaymentOptionUsed.PaymentOptionKey
      //  or maybe just grab the first one(note this would NullReferenceException on empty collection)
      //SelectedPaymentOptionKey = paymentOptions.FirstOrDefault().PaymentOptionKey 
    });
} 

次に、ビューで:

@foreach (var opt in Model.PaymentOptions)
{          
  @*Any other HTML here that you want for displaying labels or styling*@
  @Html.RadioButtonFor(m => m.SelectedPaymentOptionKey, opt.PaymentOptionKey)
}

M.SelectedPaymentOptionKeyには2つの目的があります。まず、ラジオボタンをグループ化して、選択が相互に排他的になるようにします(FireBugのようなものを使用して、生成されたhtmlを自分の理解のために検査することをお勧めします。MVCの素晴らしい点は、生成されたHTMLがかなり基本的で標準的であることですしたがって、最終的にビューの動作を予測できるようになるのは難しいことではありません。ここで行われている魔法はほとんどありません。)次に、ポストバック時に選択したアイテムの値を保持します。

そして最後に、ポストハンドラーでSelectedPaymentOptionKeyを使用できます。

[HttpPost]
public ActionResult PaymentSelection(PaymentSelectionVM vm)
{
   currentOrder.PaymentOption = db.PaymentOptions.Find(vm.SelectedPaymentOptionKey);
   ....
}

SelectListItemsを使用する場合の利点は、グリッド/テーブルを表示していて、オブジェクトの多くの値を表示する必要がある場合に、より多くのオブジェクトのプロパティにアクセスできることです。また、他のいくつかのアプローチのように、ハードコードされた文字列がHtmlヘルパーに渡されないことも気に入っています。

欠点は、すべて同じIDを持つラジオボタンが表示されることです。これは実際には良い習慣ではありません。これは、次のように変更することで簡単に修正できます。

  @Html.RadioButtonFor(m => m.SelectedPaymentOptionKey, opt.PaymentOptionKey, new { id = "PaymentOptions_" + opt.PaymentOptionKey})

最後に、検証は、私が見たほとんどすべてのラジオボタンテクニックで少し風変わりです。本当に必要な場合は、ラジオボタンがクリックされるたびに非表示のSelectedPaymentOptionsKeyを設定するために、jqueryを接続し、非表示のフィールドに[Required]またはその他の検証を配置します。

検証の問題の別の回避策 ASP.NET MVC 3の目立たない検証とラジオボタン

これは有望に見えますが、テストする機会がありませんでした: http://memoriesdotnet.blogspot.com/2011/11/mvc-3-radiobuttonlist-include.html

4
AaronLS

オプションをViewModelのSelectListにバインドし、以前に選択したオプションのSelected属性をtrueに設定する必要があります

0
Mikhail