ASP.NET MVC 基于强类型视图下 对模型以及模型中List 字段的同时编辑 表单提交


第一次发文章,排版上简单粗糙了些。如果内容中有什么错误之处,欢迎指正。相互学习,共同提高。

本人受http://shiyousan.com/post/635383025861004585  此文启发。尊重原创。

大多数时候我们提交的web表单内容都是之前就决定好的。

比如在 csdn 个人主页中编辑简介的时候看到的表单。

 

这样的表单是固定的,因为它足够简单,而且被扩展的可能性也不大。

但是你总会遇到一些让你头疼的需求。

不多废话,我们直接进主题。

假如我们有一个实体类A,A中有一个属性 List<B> Member。

代码如下:   

 1     public class Dept
 2 
 3     {
 4 
 5         public int Id { get; set; }
 6 
 7         public string Name { get; set; }
 8 
 9         public string Description { get; set; }
10 
11         public List<Employee> Members {get; set; }
12 
13     }
14 
15  
16 
17     public class Employee
18 
19     {
20 
21         public int Id { get; set; }
22 
23         public string Name { get; set; }
24 
25         public int Age { get; set; }
26 
27     }
View Code

 

我们希望在编辑Dept的时候也可以同时编辑Members中的各个子集Employee。

我们先在Dept控制器中创建Index方法,并在其中初始化一点测试数据。具体如下:

 1 public class DeptController : Controller
 2 
 3 {
 4 
 5     public ViewResult Index()
 6 
 7     {
 8 
 9         var dept = new Dept() {
10 
11             Id = 1,
12 
13             Name = "First Dept",
14 
15             Description = string.Empty,
16 
17             Members = newList<Employee>()
18 
19         };
20 
21         dept.Members.Add(new Employee() {
22 
23             Id = 1,
24 
25             Name = "犀利的绵羊",
26 
27             Age = 24
28 
29         });
30 
31         return View(dept);
32 
33     }
34 
35  
36 
37     [HttpPost]
38 
39     public ActionResult Index(Dept dept)
40 
41     {
42 
43         var membersCount = dept.Members.Count;
44 
45         var t = dept;
46 
47         return Json("done",JsonRequestBehavior.DenyGet);
48 
49     }
50 
51 }
View Code

 

接下来我们创建Index视图,我们可以看到Index方法中的视图模型是Dept类,在Index视图起始位置写上@model Dept(注意:如果运行出错,可以在Dept之前加上完整的命名空间,也可以在Views目录下的web.config文件中添加命名空间,类似<addnamespace="YourNamespace" />)

 1 @modelDept
 2 
 3  
 4 
 5 @using(Html.BeginForm())
 6 
 7 {   
 8 
 9     <div>
10 
11         <table >
12 
13             <caption>部门信息</caption>
14 
15             <tr>
16 
17                 <td>名称</td>
18 
19                <td>@Html.TextBoxFor(x=>x.Name)</td>
20 
21             </tr>
22 
23             <tr>
24 
25                 <td>描述</td>
26 
27                <td>@Html.TextBoxFor(x=>x.Description)</td>
28 
29             </tr>
30 
31             <tr>
32 
33                 <td>成员</td>
34 
35                 <td>
36 
37                     <ul>
38 
39                         @for(var i = 0; i <Model.Members.Count; i++)
40 
41                         {
42 
43                             <li>
44 
45                                 姓名:@Html.TextBoxFor(x=>x.Members[i].Name)
46 
47                                 年龄:@Html.EditorFor(x=>x.Members[i].Age)
48 
49                                 <inputtype="button" value="删除" class="deleteMember" />
50 
51                             </li>
52 
53                         }
54 
55                     </ul>
56 
57                 </td>
58 
59             </tr>
60 
61         </table>
62 
63     </div>
64 
65     <input type="submit"value="保存"/>
66 
67 }
View Code

我们可以看到,在处理Members时,我们用到了for循环和Html辅助方法。

生成的姓名和年龄对应的文本框的id和name属性都会包含for循环中 i 的值,也就是下标。截图如下:

 

下图是生成的页面

 

接下来就是前端的工作了,js代码如下:

  1 $(function() {
  2 
  3     init();
  4 
  5 })
  6 
  7  
  8 
  9 function init() {
 10 
 11     $(".addMember").remove();
 12 
 13    $(".deleteMember").last().after("<input type='button'value='添加' class='addMember'/>");
 14 
 15     initAddBtn();
 16 
 17     initDeleteBtn();
 18 
 19 }
 20 
 21  
 22 
 23 function initDeleteBtn() {
 24 
 25     $(".deleteMember").unbind();
 26 
 27     $(".deleteMember").click(function() {
 28 
 29         var memberCount =$(".deleteMember").length;
 30 
 31         if (memberCount <= 1) {
 32 
 33             alert("温馨提示:至少得有一个员工哦");
 34 
 35             return false;
 36 
 37         }
 38 
 39  
 40 
 41         // 修改当前员工下方的所有员工的可编辑框的属性(id, name)
 42 
 43        $(this).parents("li").nextAll().each(function () {
 44 
 45             // 获取输入框
 46 
 47             var txts =$(this).children("input[type='text'], input[type='number']");
 48 
 49             // 获取当前员工name属性中的数字,也就是 Members 属性的下标
 50 
 51             var index =Number(txts.eq(0).attr("name").match(/\d+/)[0]);
 52 
 53             txts.each(function () {
 54 
 55                 // 修改属性中的数字的值, 当前员工下标 -1
 56 
 57                 $(this).attr("id",$(this).attr("id").replace(/\d+/, index - 1));
 58 
 59                 $(this).attr("name",$(this).attr("name").replace(/\d+/, index - 1));
 60 
 61             })
 62 
 63         })
 64 
 65         // 删除当前 li 标签
 66 
 67        $(this).parents("li").remove();
 68 
 69         init();
 70 
 71     });
 72 
 73 }
 74 
 75 function initAddBtn() {
 76 
 77     $(".addMember").unbind();
 78 
 79     $(".addMember").click(function (){
 80 
 81         // 复制当前 li 标签,并添加到当前 li 标签后面,形成添加效果
 82 
 83         var parent =$(this).parents("li").clone();
 84 
 85        $(this).parents("li").after(parent);
 86 
 87  
 88 
 89         // 清空复制项的各个编辑框
 90 
 91         var txts =parent.children("input[type='text'], input[type='number']");
 92 
 93         txts.val("");
 94 
 95  
 96 
 97         // 获取复制项中“姓名”框的name属性中的数字,也就是 Members 属性的下标
 98 
 99         var index =Number($(this).siblings().eq(0).attr("name").match(/\d+/)[0]);
100 
101         txts.each(function () {
102 
103             // 新增的员工的 Member 下标 +1
104 
105             $(this).attr("id",$(this).attr("id").replace(/\d+/, index + 1));
106 
107             $(this).attr("name",$(this).attr("name").replace(/\d+/, index + 1));
108 
109         })
110 
111         // 删除当前 “添加” 按钮
112 
113         $(this).remove();
114 
115         init();
116 
117     })
118 
119 }
View Code

 

需要注意的是“添加”和“删除”按钮的点击事件的处理逻辑(就好像操作List一样,删除List中的一个元素,则后方的所有元素的下标要-1, 添加的元素在尾部,其下标值是List.Count - 1)。

当我们提交这个表单的时候,Dept的其他字段不用特别在意,但是Members字段的所有下标不能间断,且需从0开始,依次递增。

下面附上调试截图为依据:(生成的html不太好看,下图中的html是经过调整的)

 

点击“保存”,然后我们可以看到如下的调试信息,此时的dept.Members有三个元素。而且各个元素的属性与填写的表单内容一致。

 

 

现在我们修改一下html中的一部分,再看看操作操作结果:

 

我们可以看到第三个元素的下标改成了3,形成了0,1,3 的不连续的情况。点击“保存”,我们看调试信息:

 

我们可以看到只接收到前两个元素。不连续的第三个元素已经丢失。

我们再看看第一个元素下标不为零的情况:

 

 

可以看到Members没有接收到任何元素。

现在我们证实了上面的观点。

 

下面我们来引申一下,如果我们试图的模型是List<Employee>而不是Dept,我们是不是也可以用这种方法做到多个元素同时编辑?我想应该是没问题的。不用那些JS插件,我们一样可以实现行内编辑哦。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM