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

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

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

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

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-2 .net-3.5


    【解决方案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
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-06
      • 2018-12-10
      • 2011-03-04
      • 2018-10-04
      • 2015-12-22
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 2018-07-24
      相关资源
      最近更新 更多