有没有办法将复选框列表绑定到 asp.net mvc 中的模型

Posted

技术标签:

【中文标题】有没有办法将复选框列表绑定到 asp.net mvc 中的模型【英文标题】:Is there any way to bind a checkbox list to a model in asp.net mvc 【发布时间】:2011-06-20 18:59:04 【问题描述】:

我正在寻找一种快速简便的方法来在模型中发生回发时绑定复选框列表项列表。

显然现在常见的做法似乎是这样form.GetValues("checkboxList")[0].Contains("true"); 看起来很痛苦而且并不完全安全。

有没有办法在UpdateModel(myViewModel, form.ToValueProvider()); 阶段绑定复选框列表(在视图中使用或不使用助手创建)甚至是一组数据,这将填充IList<string> 或@ 987654324@在模型里面?

【问题讨论】:

【参考方案1】:

你可以从一个模型开始:

public class MyViewModel

    public int Id  get; set; 
    public bool IsChecked  get; set; 

然后是控制器:

public class HomeController : Controller

    public ActionResult Index()
    
        var model = new[] 
        
            new MyViewModel  Id = 1, IsChecked = false ,
            new MyViewModel  Id = 2, IsChecked = true ,
            new MyViewModel  Id = 3, IsChecked = false ,
        ;
        return View(model);
    

    [HttpPost]
    public ActionResult Index(IEnumerable<MyViewModel> model)
    
        // TODO: Handle the user selection here
        ...
    

一个视图 (~/Views/Home/Index.aspx):

<% using (html.BeginForm())  %>
    <%=Html.EditorForModel() %>
    <input type="submit" value="OK" />
<%  %>

最后是对应的编辑器模板:

<%@ Control 
    Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.MyViewModel>" %>
<%= Html.HiddenFor(x => x.Id) %>
<%= Html.CheckBoxFor(x => x.IsChecked) %>

现在,当您在 POST 操作中提交表单时,您将获得所选值的列表及其 ID。

【讨论】:

这个想法还不错,但是当您将表单与其他项目一起使用时,它就不起作用了。比如说有一个用户名/密码+一个复选框的集合,这样它就不能工作:/ @Erick,当然可以。您的视图模型现在将包含简单的属性,例如 UsernamePassword 以及包含复选框信息的集合属性 IEnumerable&lt;MyViewModel&gt;。现在,您无需在表单中使用 Html.EditorForModel,而是使用简单的 &lt;%= Html.TextBoxFor(x =&gt; x.Username) %&gt;&lt;%= Html.PasswordFor(x =&gt; x.Password) %&gt; 以及 &lt;%= Html.EditorFor(x =&gt; x.MyCheckboxes) %&gt;,它们将呈现相同的编辑器模板。 我阅读了许多实现此目的的方法,这是迄今为止最优雅的解决方案。谢谢!【参考方案2】:

这是快速简便的方法。只需在checkbox 输入元素中设置value 属性,并为它们提供相同的name如果我在站点中实现此功能,我将创建一个 CheckBox 辅助方法,该方法采用 namevalueisChecked 参数,但这里是只需要 html 的视图:

<% using (Html.BeginForm())  %>
  <p><input type="checkbox" name="checkboxList" value="Value A" /> Value A</p>
  <p><input type="checkbox" name="checkboxList" value="Value B" /> Value B</p>
  <p><input type="checkbox" name="checkboxList" value="Value C" /> Value C</p>
  <p><input type="checkbox" name="checkboxList" value="Value D" /> Value D</p>
  <p><input type="checkbox" name="checkboxList" value="Value E" /> Value E</p>
  <p><input type="checkbox" name="checkboxList" value="Value F" /> Value F</p>
  <input type="submit" value="OK" />
<%  %>

在你的控制器中:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(IEnumerable<string> checkboxList)

    if (checkboxList != null)
    
        ViewData["Message"] = "You selected " + checkboxList.Aggregate("", (a, b) => a + " " + b);
    
    else
    
        ViewData["Message"] = "You didn't select anything.";
    

    return View();

IEnumerable&lt;string&gt; 参数(如果需要,您可以将其设为IList&lt;string&gt;)将仅包含选中项的值。如果没有选中任何框,它将是null

【讨论】:

我认为将原生 html 代码放在那里不是一个好主意,因为如果用户想将模型绑定到复选框会很痛苦 @tugberk,我说过我会在生产代码中使用辅助方法。我只是想展示原始问题的答案。我将添加辅助方法代码。 这是正确答案。如果您尝试使用内置的 Html.CheckBox() 助手,他们坚持使用 value="false" 插入隐藏字段,这会干扰模型绑定。【参考方案3】:

使用自定义模型绑定器和常规 HTML 可以很好地工作...

首先,使用 Razor 语法的 HTML 表单:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) 
    <ol>
        <li><input type="textbox" name="tBox" value="example of another form element" /></li>

        <li><input type="checkbox" name="cBox" value="1" /> One</li>
        <li><input type="checkbox" name="cBox" value="2" /> Two</li>
        <li><input type="checkbox" name="cBox" value="3" /> Three</li>
        <li><input type="checkbox" name="cBox" value="4" /> Four</li>
        <li><input type="checkbox" name="cBox" value="5" /> Five</li>

        <li><input type="submit" /></li>
    </ol>

FormMethod.Post也可以是.Get,没关系)

然后,在正确的 MVC 意义上,有一个模型对象代表您的表单提交:

public class CheckboxListExampleModel 
    public string TextboxValue  get; set; 
    public List<int> CheckboxValues  get; set; 

还有一个自定义模型绑定器类(我喜欢将它放在要绑定的模型中,所以我将重复上面创建的模型以显示我要添加它的位置。将它放在里面还允许绑定器使用私有属性setters,这是一件好事):

public class CheckboxListExampleModel 
    public string TextboxValue  get; private set; 
    public List<int> CheckboxValues  get; private set; 

    public class Binder : DefaultModelBinder 
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
            var model = new CheckboxListExampleModel();

            model.TextboxValue = bindingContext.GetValueAsString("tBox");

            string checkboxCsv = bindingContext.GetValueAsString("cBox");
            // checkboxCsv will be a comma-separated list of the 'value' attributes
            //   of all the checkboxes with name "cBox" which were checked
            model.CheckboxValues = checkboxCsv.SplitCsv<int>();

            return model;
        
    

.GetValueAsString()是为了清晰起见的扩展方法,这里是:

    public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) 
        var providerResult = context.ValueProvider.GetValue(formValueName);
        if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) 
            if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) 
                return null;
             else 
                return providerResult.AttemptedValue.Trim();
            
        
        return null;
    

.SplitCsv&lt;T&gt;() 也是一种扩展方法,但它是一个足够普遍的需求和足够混乱的代码,我将把它作为练习留给读者。

最后,您处理表单提交的操作:

[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) 
    // stuff

【讨论】:

以上是关于有没有办法将复选框列表绑定到 asp.net mvc 中的模型的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core Razor 页面中绑定复杂列表

使用 jquery 创建一个列表并将其发布到 asp.net mvc

将 ListItem 的 ASP.NET 列表数据绑定到 DropDownList 问题

将 JSON 数组绑定到 ASP.NET MVC 3 中的列表的故障模型

如何在 asp.net checkboxlist 中设置多个选定的值

如何将项目列表从视图传递到控制器(ASP.NET MVC 4)