强类型RadioButtonlist

时间:2011-04-14 08:16:59

标签: asp.net-mvc-3 razor radiobuttonlist

我想获得一些选项(比如付款方式现金,信用卡等)并将这些选项绑定到单选按钮。我相信MVC 3中没有RadioButtonList。

此外,一旦绑定了无线电,我想在编辑答案时向用户显示以前选择的选项。

3 个答案:

答案 0 :(得分:37)

与往常一样,您要从模型开始:

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" />
}

如果您想要一些更通用的解决方案,将其封装在帮助器中,您可能会发现following answer很有帮助。

答案 1 :(得分:4)

这就是我喜欢绑定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有两个目的。首先,它将单选按钮组合在一起,以便选择是互斥的(我鼓励你使用像FireBug这样的东西来检查生成的html只是为了你自己的理解。关于MVC的好处是生成的HTML是相当基本和标准的所以你最终能够预测你的观点的行为并不困难。这里几乎没有什么魔力。)其次,它将在回发中保留所选项目的值。

最后在post处理程序中,我们有了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})

最后,对于我见过的大多数单选按钮技术,验证有点古怪。如果我真的需要它,我会在点击单选按钮时连接一些jquery来填充隐藏的SelectedPaymentOptionsKey,并将[Required]或其他验证放在隐藏字段上。

验证问题的另一种解决方法 ASP.NET MVC 3 unobtrusive validation and radio buttons

这看起来很有希望,但我没有机会测试它: http://memoriesdotnet.blogspot.com/2011/11/mvc-3-radiobuttonlist-including.html

答案 2 :(得分:0)

您应该将选项绑定到ViewModel中的SelectList,并将Selected属性设置为true以用于先前选择的选项