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

时间:2011-02-03 16:15:10

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

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

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

是否有办法绑定复选框列表(在视图中使用或不使用帮助程序创建),或者甚至是UpdateModel(myViewModel, form.ToValueProvider());阶段内的数据数组,这将填充{{1在模型里面还是IList<string>

3 个答案:

答案 0 :(得分:9)

你可以从模特开始:

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。

答案 1 :(得分:9)

这是快速简便的方法。只需在value输入元素中设置checkbox属性,并为它们提供相同的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<string>参数(如果需要,可以使其为IList<string>)将仅包含已检查项目的值。如果没有选中任何框,则为null

答案 2 :(得分:0)

使用自定义模型绑定器和常规HTML ...

可以很好地工作

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

@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; }
}

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

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<T>() 也是一种扩展方法,但这是一个很常见的需求和足够混乱的代码,我将把它作为读者的练习。

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

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