MVC5之表单集合数据自动绑定到对象属性(集合)中

本文介绍如何在ASP.NET MVC项目中实现复杂类型的表单数据绑定,包括使用Html.TextBoxFor处理集合属性,并通过动态添加表单项来满足实际需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

##前言 之前没遇到过这个问题,在项目中遇到这个问题时想法挺好,按照流程走下去,结果事与愿违,于是开始探索着解决方案,接下来我们来看看这个问题,早已经明了的童鞋请绕道,此文仅供未遇到的童鞋提供一种解决方案。

话题

首先我们来看看整个问题的出现,介绍一下问题的背景。

     public class Blog
    {
        public string BlogName { get; set; }
        public string BlogAddress { get; set; }
        public List<Article> Article { get; set; }
    }

    public class Article
    {
        public string ArticleIntr { get; set; }
        public string ArticleName { get; set; }
    }
上述给出两个类,一个博客包含多篇文章取集合属性。
public ActionResult Test(Blog b)
        {
            var articleList = new List<Article>() { new Article() { ArticleIntr = "asp.net mvc", ArticleName = "mvc" }, new Article { ArticleIntr = "WebAPi", ArticleName = "WebAPi Authentication" } };
            var blog = new Blog() { BlogName = "xpy0928", BlogAddress = "CreateMyself", Article = articleList };           
            return View(blog);
        }

利用强类型视图渲染到页面

@using FormToObjList.Models
@model Blog
@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<div style="width:700px;margin-left:200px;">
    <form action="test" method="post" enctype="multipart/form-data">
        <div style="float:left;">
            博客地址:<input type="text" class="form-control" value="@Model.BlogAddress" /><br />
            博客名称:<input type="text" class="form-control" value="@Model.BlogName" /><br />
        </div>
        <br />

        <div style="float:right;">
            <table>
                <tr>
                    <th>序号</th>
                    <th>文章介绍</th>
                    <th>文章名称</th>
                </tr>
                @{
                    var i = 0;
                    foreach (var article in Model.Article)
                    {
                        <tr>
                            <td>@(++i)</td>
                            <td><input type="text" class="form-control" value="@article.ArticleIntr" /></td>
                            <td><input type="text" class="form-control" value="@article.ArticleName" /></td>
                        </tr>
                    }
                }
            </table>
        </div>
        <div style="clear:both;float:right;">
            <button class="btn btn-primary" type="submit">提交</button>
        </div>
    </form>
</div>

到这里我们需要实现的是点击提交后将页面上所有的数据都添加到后台【Blog b】属性,着重强调的是获取到b中属性Article要有两条我们渲染的数据。

我们看看演示结果:
这里写图片描述

我们可以看到居然都为空,别着急,此时都会想到既然要获取到值,则文本的name属性要和类中的属性一一对应才是,说完就开干。

  博客地址:<input type="text" name="BlogAddress" class="form-control" value="@Model.BlogAddress" /><br />
  博客名称:<input type="text" name="BlogName"    class="form-control" value="@Model.BlogName" /><br />



 <td><input type="text" name="ArticleIntr" class="form-control" value="@article.ArticleIntr" /></td>
 <td><input type="text" name="ArticleName" class="form-control" value="@article.ArticleName" /></td>

进行如上设置后我们再来看看结果:
这里写图片描述

恩,有点小忧伤,对于Article这个集合属性数据并未添加到其中去,这个就是我们需要解决的问题。到了这里我寻思着是不是不能用html标签,需要用mvc自己来渲染成html标签才行呢?也就是说利用【 @Html.TextBoxFor() 】来进行渲染,此时是个集合,则只能用for循环来进行遍历,于是乎将数据渲染时修改成下面的这个样子。

               @{
                    var j = 0;
                    for (var i = 0; i < Model.Article.Count; i++)
                    {
                        <tr>
                            <td>@(++j)</td>
                            <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class="form-control"})</td>
                            <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class="form-control"})</td>
                        </tr>
                    }
                }

我们继续看看结果:
这里写图片描述

好了,我们终于得到我们想要的结果了,你是不是觉得就这么愉快的结束了呢?

实际需求

在项目中我们需要做的是添加,同时在页面开始时有几个默认的文本框且还需要动态添加行,这个时候我们又该如何做呢?我们一起来看看。

               @{
                    if (Model.Article != null)
                    {
                        var j = 0;
                        for (var i = 0; i < Model.Article.Count; i++)
                        {
                            <tr>
                                <td>@(++j)</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class = "form-control" })</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class = "form-control" })</td>
                            </tr>
                        }
                    }
                    else 
                    {

                    }
                }

如果默认没有值时,我们则需要自己添加默认的文本,此时该如何添加,我们想想当直接利用htm文本标签和利用Html.TextBoxFor渲染的效果有何不同?看看如下:

//Html标签
<input type="text" name="ArticleIntr" class="form-control" value="WebAPi">


//Html.TextBoxFor()
<input class="form-control" id="Article_1__ArticleIntr" name="Article[1].ArticleIntr" type="text" value="Angular">

这个时候我们恍然大悟,既然是集合那么name则是取到对应的索引值,我们照样画葫芦,于是我们修改成如下:

                @{
                    if (Model.Article != null)
                    {
                        var j = 0;
                        for (var i = 0; i < Model.Article.Count; i++)
                        {
                            <tr>
                                <td>@(++j)</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class = "form-control" })</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class = "form-control" })</td>
                            </tr>
                        }
                    }
                    else
                    {
                        var j = 0;
                        for (var i = 0; i < 3; i++)
                        {
                            <tr id="trs">
                                <td>@(++j)</td>
                                <td><input type="text" name="Article[@i].ArticleIntr" class="form-control" /></td>
                                <td><input type="text" name="Article[@i].ArticleName" class="form-control" /></td>
                            </tr>
                        }
                    }
                }

动态添加时的操作:

        $("#btnAdd").on("click", function () {
            var trLen = $("#tb tr[id='trs']").length;
            var $lastTr = $("#tb tr[id='trs']").last();
            var tr = "<tr id='trs'>";
            tr += "<td>" + (trLen + 1) + "</td>";
            tr += "<td><input type='text' name='Article[" + trLen + "].ArticleIntr' class='form-control' /></td>";
            tr += "<td><input type='text' name='Article[" + trLen + "].ArticleName' class='form-control' /></td>";
            tr += "</tr>";
            $(tr).insertAfter($lastTr);
        });

完整效果如下:
这里写图片描述

至此我们的需求才算结束。

总结

项目中渲染视图都是采用MVC中Razor渲染的方式,所以在做的时候也是跟着项目同样的风格去做,做的时候才发现这个问题并解决了下,学习,学习,可能还有其他解决方案,这也算是其中一种吧。

<think>我们正在讨论SpringMVC表单标签库,特别是关于如何绑定集合数据的标签。根据引用内容,我们知道SpringMVC表单标签库包含一组标签,用于在JSP页面中渲染表单元素,并支持数据绑定。特别地,引用[2]提到了一些子标签,包括checkboxs和radiobuttons,这些标签可以用于处理多个选项(即集合数据)。另外,引用[5]也提到了使用表单标签库需要在JSP页面开头声明taglib指令。在SpringMVC表单标签库中,绑定集合数据的标签主要有:1.`<form:checkboxes>`:用于生成一组复选框,绑定到一个集合(如List)的值。2.`<form:radiobuttons>`:用于生成一组单选按钮,绑定到一个集合的值。3.`<form:select>`和`<form:options>`:`<form:select>`用于生成下拉列表,而`<form:options>`可以生成一组下拉选项,这些选项可以绑定到一个集合。下面我们详细解释这些标签的用法:1.`<form:checkboxes>`标签:这个标签用于生成多个复选框。它需要绑定到一个对象属性,该属性是一个集合(如数组、List等),并且需要提供一个选项列表(items属性),这个列表通常是一个Map、List或者数组。例如,假设我们有一个用户对象,该对象有一个属性`interests`,它是一个List,存用户选择的兴趣。同时,我们有一个可选的兴趣列表(比如从模型数据中获取的allInterests)。在JSP中我们可以这样写:```jsp<form:checkboxespath="interests"items="${allInterests}"/>```这里,`path`属性指定了绑定到用户对象的`interests`属性,`items`属性指定了所有的可选项(即allInterests)。在渲染时,会为allInterests中的每一项生成一个复选框,并且根据用户对象的interests集合中的值自动选中相应的复选框。2.`<form:radiobuttons>`标签:这个标签用于生成多个单选按钮。与checkboxes类似,它需要绑定到一个对象属性(注意,单选按钮绑定的是单个值,而不是集合,因为单选只能选一个),但它的选项也是来自一个集合。例如,绑定一个用户的性别(gender)属性,可选项为“男”、“女”:```jsp<form:radiobuttonspath="gender"items="${genders}"/>```这里,`genders`是一个包含两个字符串("男"和"女")的List。在渲染时,会生成两个单选按钮,并根据用户对象的gender属性自动选中其中一个。3.`<form:select>`和`<form:options>`标签:`<form:select>`用于生成一个下拉选择框,而`<form:options>`用于生成下拉框中的选项。它们也可以绑定集合数据(例如,下拉框的多选模式可以绑定到一个集合)。例如,用户可以选择多个角色(roles):```jsp<form:selectpath="roles"multiple="true"><form:optionsitems="${allRoles}"/></form:select>```这里,`path="roles"`绑定到用户对象的roles属性(一个集合),`multiple="true"`表示允许多选,`items="${allRoles}"`提供了所有可选的角色列表。另外,也可以使用`<form:select>`直接配合items属性:```jsp<form:selectpath="roles"items="${allRoles}"multiple="true"/>```需要注意的是,对于绑定集合数据的标签,后台的Controller方法中需要将模型数据(如allInterests,allRoles等)添加到模型中,以便在表单渲染时使用。此外,引用[4]展示了一个简单的数据绑定例子:Controller方法中的参数`Citycity`会自动绑定表单数据到City对象。总结:在SpringMVC表单标签库中,用于绑定集合数据的标签主要有`<form:checkboxes>`,`<form:radiobuttons>`(虽然单选绑定的是单个值,但它的选项来自集合,并且可以用于多选一的情况),以及`<form:select>`(配合multiple属性可以绑定集合)。下面我们通过一个示例来展示这些标签的使用:假设我们有一个User类,包含以下属性:privateList<String>interests;//兴趣列表privateStringgender;//性别privateList<String>roles;//角色列表(多选)在Controller中,我们需要准备模型数据:@GetMapping("/register")publicStringshowRegistrationForm(Modelmodel){Useruser=newUser();model.addAttribute("user",user);//表单绑定对象//准备可选项List<String>interestsList=Arrays.asList("体育","音乐","旅游");model.addAttribute("interestsList",interestsList);List<String>genders=Arrays.asList("男","女");model.addAttribute("genders",genders);List<String>rolesList=Arrays.asList("管理员","编辑","普通用户");model.addAttribute("rolesList",rolesList);return"register";}在register.jsp页面中:<%@taglibprefix="form"uri="http://www.springframework.org/tags/form"%><form:formmodelAttribute="user"method="post">兴趣:<br/><form:checkboxespath="interests"items="${interestsList}"/><br/>性别:<br/><form:radiobuttonspath="gender"items="${genders}"/><br/>角色:<br/><form:selectpath="roles"items="${rolesList}"multiple="true"/><br/><inputtype="submit"value="提交"/></form:form>这样,当表单提交时,用户选择的兴趣(多个)会绑定到user.interests,性别(一个)绑定到user.gender,角色(多个)绑定到user.roles。注意:`<form:select>`标签的multiple属性设置为true时,表示可以选择多个选项,因此绑定的path应该是一个集合类型。以上就是SpringMVC表单标签库中用于绑定集合数据的标签及其用法。最后,根据要求,生成相关问题:§§相关问题§§1.SpringMVC表单标签库中如何绑定对象类型的集合?2.除了checkboxes、radiobuttons和select,还有哪些表单标签可以用于绑定集合数据?3.如何在SpringMVC表单标签库中实现嵌套集合绑定(比如List中的对象属性)?4.表单标签库在数据绑定过程中如何实现类型转换?</think>### Spring MVC 表单标签绑定集合数据的标签详解 在 Spring MVC 表单标签库中,绑定集合数据主要通过以下三个核心标签实现: #### 1. **`<form:checkboxes>` 标签** 用于渲染一组复选框,绑定集合类型属性(如 `List`、`Set`)。 **语法示例**: ```jsp <form:checkboxes path="selectedRoles" items="${allRoles}" /> ``` - **`path`**:绑定到模型对象集合属性(如 `user.selectedRoles`) - **`items`**:从模型数据获取的选项集合(如 `${allRoles}`) - **工作原理**:自动将用户选择的多个值绑定集合属性,支持数据回显[^2][^5]。 #### 2. **`<form:radiobuttons>` 标签** 用于渲染一组单选按钮,绑定到单个属性(非集合),但选项源可以是集合。 **语法示例**: ```jsp <form:radiobuttons path="gender" items="${genders}" /> ``` - **`path`**:绑定到模型对象的单个属性(如 `user.gender`) - **`items`**:选项集合(如 `${genders = ['男','女']}`) - **注意**:虽然选项源是集合,但绑定结果是单个值[^2][^3]。 #### 3. **`<form:select>` + `<form:options>` 标签** 用于渲染下拉列表或多选框,支持绑定集合数据(需设置 `multiple="true"`)。 **绑定集合的语法**: ```jsp <form:select path="hobbies" items="${hobbyList}" multiple="true" /> ``` 或使用嵌套标签: ```jsp <form:select path="hobbies" multiple="true"> <form:options items="${hobbyList}" /> </form:select> ``` - **关键属性**: - `multiple="true"`:启用多选模式(绑定集合必备) - `items`:选项集合(支持 `List`、`Map` 或对象数组) - **数据绑定**:用户选择的多个值会自动绑定到 `path` 指定的集合属性[^2][^5]。 --- ### 完整使用流程 1. **声明标签库**(JSP 头部): ```jsp <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ``` 2. **准备模型数据**(Controller 层): ```java @GetMapping("/edit") public String showForm(Model model) { User user = new User(); user.setSelectedRoles(Arrays.asList("ADMIN", "EDITOR")); // 初始化已选项 model.addAttribute("user", user); model.addAttribute("allRoles", Arrays.asList("ADMIN", "EDITOR", "USER")); // 选项集合 return "edit-form"; } ``` 3. **表单渲染**(JSP 视图): ```jsp <form:form modelAttribute="user"> <!-- 绑定角色集合 --> <form:checkboxes path="selectedRoles" items="${allRoles}" delimiter="<br/>"/> <!-- 绑定多选爱好 --> <form:select path="hobbies" items="${hobbies}" multiple="true"/> </form:form> ``` 4. **数据提交绑定**(Controller 接收): ```java @PostMapping("/save") public String save(@ModelAttribute User user) { // user.getSelectedRoles() 自动包含表单提交的集合数据 // user.getHobbies() 自动绑定多选值 } ``` --- ### 关键特性总结 | 标签 | 绑定数据类型 | 多选支持 | 数据回显 | |---------------------|--------------|----------|----------| | `<form:checkboxes>` | 集合(List/Set) | ✔️ | ✔️ | | `<form:radiobuttons>`| 单值 | ✘ | ✔️ | | `<form:select multiple>` | 集合 | ✔️ | ✔️ | > **注意**:集合绑定要求模型对象属性必须为集合类型(如 `List<String>`),且需预先初始化(避免 `NullPointerException`)[^2][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值