忽然发现周围的人都是高级编程人员,而我是介于初级和高级之间。顺便吟诗一首,“千山鸟飞绝,万径人踪灭。野旷天低树,江清月近人。”,,我们进入正题。首先来看一下效果图
本篇文章和上篇文章讲的是同一个界面,但是本片讲述的AJAX实现。首先,先看前台代码
@using MVCRestServiceDemo.Models.Response; @using MVCRestServiceDemo.Models; @model DataResponse<person_info> <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>档案信息</title> <script type="text/javascript" src="~/Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> <script type="text/javascript"> jQuery(document).ready(function () { setRowBackColor(); $("#btnQuery").click(function () { /*查询*/ queryData(); }); }); function queryData() { var pageIndex = 1; var pageSize = 10; var no = $("#txtNo").val(); var name = $("#txtName").val(); var sex = $("#ddlSex").val(); var condition = pageIndex + "_" + pageSize + "_" + no + "|" + name + "|" + sex; $.ajax({ url: "/Home/GetArchiveInfoByConditionAjax/" + condition, type: "POST", datatype: "Html", beforeSend: function () { $("#updateProgressDiv").show(); }, complete: function () { $("#updateProgressDiv").hide(); }, success: function (data) { $("#archiveInfoPartialDiv").html(data); setRowBackColor(); }, error: function () { alert("查询失败!"); } }); } function checkall() { /*全选*/ if ($("#chkall").attr("checked")) { $(".mytable :checkbox").attr("checked", true); } else { $(".mytable :checkbox").attr("checked", false); } } function setRowBackColor() /*隔行变色*/ { var t = document.getElementById("tabArchiveInfo").getElementsByTagName("tr"); for (var i = 0; i < t.length; i++) { t[i].style.backgroundColor = (t[i].sectionRowIndex % 2 == 0) ? "#b7b3b3" : "#fff"; } } function setCheck(id) /*点击行选中或取消选中行首复选框*/ { $("#chk_" + id).attr("checked", !$("#chk_" + id).attr("checked")); } function ShowArchiveInfoModify(no) { var w = (screen.width - 500) / 2; var h = (screen.height - 210) / 2; var paramStr = "dialogWidth=500px;dialogHeight=210px;dialogTop=" + h + "px;dialogLeft=" + w + "px;center=yes;middle=yes;help=no;status=no;scroll=no;resizable:no;location:no;"; window.showModalDialog("/Home/ShowArchiveInfoModify/" + no, null, paramStr); queryData(); } </script> </head> <body> <div style="margin: 10px" align="center"> @using (Ajax.BeginForm("Delete", "Home", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "archiveInfoPartialDiv", InsertionModeInsertionMode = InsertionMode.Replace })) { <table style="width: 96%; margin-bottom: 3px"> <tr> <td align="right">档案编号: </td> <td align="left"> @Html.TextBox("no", string.Empty,new { id = "txtNo" }) </td> <td align="right">姓名: </td> <td align="left"> @Html.TextBox("name", string.Empty, new { id = "txtName" }) </td> <td align="right">性别: </td> <td align="left"> @Html.DropDownList("sex", (TempData["selectList"] as SelectList), new { id = "ddlSex" }) </td> <td aling="center"> <input id="btnQuery" type="button" value="查询" style="width: 80px" /> </td> </tr> </table> Html.RenderPartial("~/Views/PartialView/ArchiveInfoUserControl.cshtml"); <div style="width: 96%; margin-top: 5px" align="right"> <button type="button" style="width: 80px;">增加</button> <button type="button" style="width: 80px" id="btnDelete">删除</button> </div> } </div> <div id="updateProgressDiv" style="display: none;text-align: center"> <img src="~/Images/throbber.gif" alt="loading" /> <label>正在加载,请稍后......</label> </div> </body> </html>
我们看这个queryData函数,查询的时候用的AJAX方式,当回调回来以后,将界面输出至archiveInfoPartialDiv这个DIV。这个DIV在哪呢?我们发现上面的代码中没有,那它肯定在用户控件里面了。
@using MVCRestServiceDemo.Models.Response; @using MVCRestServiceDemo.Models; @model DataResponse<person_info> <div id="archiveInfoPartialDiv"> <table class="mytable" id="tabArchiveInfo"> <tr> <th> <center> @Html.CheckBox("chk_all", new { id = "chkall", onclick = "checkall()" }) </center> </th> <th> <center>档案编号</center> </th> <th> <center>姓名</center> </th> <th> <center>性别</center> </th> <th> <center>身份证号</center> </th> <th> <center>出生日期</center> </th> <th> <center>毕业院校</center> </th> <th> <center>学历</center> </th> <th> <center>专业</center> </th> <th> <center>操作</center> </th> </tr> @foreach (var personInfo in Model.DataList) { <tr onclick="setCheck('@personInfo.id')"> <td style="text-align: center;"> @Html.CheckBox(string.Concat("chk_", personInfo.id), false, new { id = string.Concat("chk_", personInfo.id), onclick = "setCheck('" + personInfo.id + "')" }) @Html.Hidden(string.Concat("hfd_", personInfo.id), personInfo.id) </td> <td> @personInfo.no </td> <td> @personInfo.name </td> <td> @(personInfo.sex == "1" ? "男" : "女") </td> <td> @personInfo.id_card </td> <td> @personInfo.birth </td> <td> @personInfo.graduate_school </td> <td> @personInfo.education_level </td> <td> @personInfo.professional </td> <td> <button type="button" style="width: 60px; margin-right: 3px" onclick="ShowArchiveInfoModify('@personInfo.id')"> 修改 </button> <button type="submit" style="width: 60px">删除</button> </td> </tr> } </table> <div class="divpager"> 共有 <font color="red" id="ft">@Model.TotalCount</font>条记录 当前是第 <font color="red">@Model.PageIndex</font> 页 共<font color="red">@Model.TotalPages</font>页 @if (Model.HasPreviousPage) { @Ajax.ActionLink("首页", "GetArchiveInfoByConditionAjax", new { id = string.Join("_", "1", Model.PageSize, ViewBag.Conition) }, new AjaxOptions() { HttpMethod = "Get", InsertionModeInsertionMode = InsertionMode.Replace, UpdateTargetId = "archiveInfoPartialDiv",LoadingElementId="updateProgressDiv", OnSuccess="setRowBackColor();" })<label> </label> @Ajax.ActionLink("上一页", "GetArchiveInfoByConditionAjax", new { id = string.Join("_", Model.PageIndex - 1, Model.PageSize, ViewBag.Conition) }, new AjaxOptions() { HttpMethod = "Get", InsertionModeInsertionMode = InsertionMode.Replace, UpdateTargetId = "archiveInfoPartialDiv",LoadingElementId="updateProgressDiv", OnSuccess="setRowBackColor();" })<label> </label> } else { <text>首页 </text> <text>上一页 </text> } @if (Model.HasNextPage) { @Ajax.ActionLink("下一页", "GetArchiveInfoByConditionAjax", new { id = string.Join("_", Model.PageIndex + 1, Model.PageSize, ViewBag.Conition) }, new AjaxOptions() { HttpMethod = "Get", InsertionModeInsertionMode = InsertionMode.Replace, UpdateTargetId = "archiveInfoPartialDiv",LoadingElementId="updateProgressDiv", OnSuccess="setRowBackColor();" })<label> </label> @Ajax.ActionLink("末页", "GetArchiveInfoByConditionAjax", new { id = string.Join("_", Model.TotalPages, Model.PageSize, ViewBag.Conition) }, new AjaxOptions() { HttpMethod = "Get", InsertionModeInsertionMode = InsertionMode.Replace, UpdateTargetId = "archiveInfoPartialDiv",LoadingElementId="updateProgressDiv" , OnSuccess="setRowBackColor();"}) } else { <text>下一页 </text> <text>末页 </text> } </div> </div>
果然在这里。在第一段代码中,我们在点击修改按钮的时候弹出一个修改界面,即ShowArchiveInfoModify函数,这个函数接收一个参数,然后调用"/Home/ShowArchiveInfoModify/" + no这个URL,Modal页面修改完数据关闭的时候,调用queryData函数异步刷新界面。我们看到这个代码 @Ajax.ActionLink("首页", "GetArchiveInfoByConditionAjax", new { id = string.Join("_", "1", Model.PageSize, ViewBag.Conition) }, new AjaxOptions() { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "archiveInfoPartialDiv",LoadingElementId="updateProgressDiv", OnSuccess="setRowBackColor();" })。这就是我们的AJAX方式分页。关于这个Ajax.ActionLink有很多重载,具体的自己看。我这个第一个参数是超链接名字,第二个参数是Action名字,第三个参数是RouteValues,第四个参数AjaxOptions。关于这个AjaxOptions,我们看看
这个Confirm是确认信息,假如你这个链接是删除,那么你可以设置Confirm="确定要删除吗?"。如果你确定,那么就执行删除的Action,否则不执行。看到这个LoadingElementDuration,这个是指加载界面元素时弹出UpdateProgress的事件间隔,比如淘宝上查询了一批商品,那么会出一个显示正在加载的圆圈。LoadingElementID指的是显示正在加载的元素的ID,比如<div id="loadingelmentId">正在加载.......</div>。在这里我们可以看到是
<div id="updateProgressDiv" style="display: none;text-align: center"> <img src="~/Images/throbber.gif" alt="loading" /> <label>正在加载,请稍后......</label> </div>
这个层,当分页调用的时候就显示这个层,调用成功该层隐藏,注意,初始化的层是隐藏的display: none。看到这里,我们发现queryData的代码如下
$.ajax({ url: "/Home/GetArchiveInfoByConditionAjax/" + condition, type: "POST", datatype: "Html", beforeSend: function () { $("#updateProgressDiv").show(); }, complete: function () { $("#updateProgressDiv").hide(); }, success: function (data) { $("#archiveInfoPartialDiv").html(data); setRowBackColor(); }, error: function () { alert("查询失败!"); } });
在这里其实用jquery也可以轻松实现loading效果,主要的就是beforesend和complete。OnBegin,就是调用AJAX之前,OnComplete就是调用结束后,OnFailure就是调用失败,OnSuccess就是调用成功,在这里就是当异步调用成功以后,给partial页面设置隔行变色,调用setRowBackColor函数。再下来有一个HttpMethod,这个就是请求的方式POST还是GET。InsertionMode则是插入的方式,比如AJAX调用结束以后,返回的是一个页面cshtml,这个时候你要指定这个InsertionMode
我们看到有三个枚举值,一个是InsertAfter,意思是在之后插入,InsertBefore是在之前插入,Replace则是替换,由于我们在这里是分页,所以肯定是Replace,因为我们每次返回的都是一页数据。有一种场景,可能用到InsertAfter,比如,我增加一个东西,我每次增加完以后我都要看见这个东西增加成功了,这个时候,后台只需要把刚插入的这条返回,然后InsertAfter即可。InsertBefore场景比如我点击删除,然后后台返回一个由于什么原因不能删除的信息,这个时候可以显示在form的最顶,就用InsertBefore,总之InsertAfter和Before强调的增量,而Replace强调的是覆盖。最后的一个参数UpdateTargetId,意思是要更改的元素ID,一般是DIV。在这里我们每次分页要更新的是archiveInfoPartialDiv这个DIV元素。OK,前台基本没什么了。我们看看后台
public ViewResult GetArchiveInfoAjax() { string uri = string.Format(baseAddress + "PersonInfo/GetAll/{0}/{1}", 1, 10); ViewBag.Conition = string.Join("|", string.Empty, string.Empty, string.Empty); DataResponse<person_info> personInfoList = dataService.GetData<DataResponse<person_info>>(uri); this.GetSexList(); return View("~/Views/Home/ArchiveInfoAjax.cshtml", personInfoList); } public PartialViewResult GetArchiveInfoByConditionAjax(string id) { string[] pageValues = id.Split("_".ToCharArray()); int pageIndex = int.Parse(pageValues.ElementAt(0)); int pageSize = int.Parse(pageValues.ElementAt(1)); string[] searchValues = pageValues[2].Split("|".ToCharArray()); string no = searchValues.ElementAt(0) ?? string.Empty; string name = searchValues.ElementAt(1) ?? string.Empty; string sex = searchValues.ElementAt(2) ?? string.Empty; PersonRequest request = new PersonRequest() { No = no.Trim(), Name = name.Trim(), Sex = sex.Trim(), PageSize = pageSize, PageIndex = pageIndex }; ViewBag.No = request.No; ViewBag.Name = request.Name; ViewBag.Conition = string.Join("|", no.Trim(), name.Trim(), sex.Trim()); string uri = baseAddress + "PersonInfo/GetByCondition"; DataResponse<person_info> personInfoList = dataService.GetData<DataResponse<person_info>, PersonRequest>(uri, request); return PartialView("~/Views/PartialView/ArchiveInfoUserControl.cshtml", personInfoList); } public ViewResult ShowArchiveInfoModify(string id) { string uri = string.Format(string.Concat(baseAddress, "PersonInfo/GetPersonInfo/{0}"),id); person_info personInfo = dataService.GetData<person_info>(uri); this.GetSexList(string.Empty); this.GetEducationList(string.Empty); this.GetProfessionalList(string.Empty); return View("~/Views/Home/ArchiveInfoModify.cshtml",personInfo); } public JavaScriptResult ModifyPersonInfo(person_info personInfo) { if (string.IsNullOrEmpty(personInfo.education_level)) { return JavaScript("alert('学历不能为空!');"); } string uri = string.Concat(baseAddress, "PersonInfo/ModifyPersonInfo"); int suc=dataService.DealData<int, person_info>(uri,personInfo); return JavaScript("alert('修改成功!');window.close();"); } private void GetEducationList(string selectedValue="") { string uri = baseAddress + "PersonInfo/GetEducation"; List<codes> codeList = dataService.GetData<List<codes>>(uri); codeList.Insert(0, new codes() { data = string.Empty, display_content = "---请选择---" }); SelectList selectList = new SelectList(codeList, "data", "display_content", selectedValue); ViewBag.EducationList = selectList; } private void GetProfessionalList(string selectedValue = "") { string uri = baseAddress + "PersonInfo/GetProfessional"; List<codes> codeList = dataService.GetData<List<codes>>(uri); codeList.Insert(0, new codes() { data = string.Empty, display_content = "---请选择---" }); SelectList selectList = new SelectList(codeList, "data", "display_content", selectedValue); ViewBag.ProfessionalList = selectList; }
一些获取下拉列表数据,查询,获取Modal页面,修改信息。GetArchiveInfoAjax这个是初始化界面,GetArchiveInfoByConditionAjax这个是分页,和非AJAX界面不同的是,它返回的是我们的partial页PartialView("~/Views/PartialView/ArchiveInfoUserControl.cshtml", personInfoList)用这个页面去替换上一页数据。ShowArchiveInfoModify界面则是返回showModal界面,并且给它绑定一个要修改的对象。ModifyPersonInfo就是修改信息了,在这里我们写了一个简单的check,然后return JavaScript("alert('学历不能为空!');"),注意在这里,如果return JavaScript,则要在页面引用jquery.unobtrusive-ajax.min.js,否则不能正确执行javascript。好了,我们再看看我们的WCF Service
public person_info GetPersonInfo(string id) { person_info personInfo = misInfoEntities.person_info.Find(id); return personInfo; } public int ModifyPersonInfo(person_info personInfo) { person_info person_Info = misInfoEntities.person_info.Find(personInfo.id); person_Info.name = personInfo.name; person_Info.id_card = personInfo.id_card; person_Info.sex = personInfo.sex; person_Info.education_level = personInfo.education_level; person_Info.professional = personInfo.professional; person_Info.graduate_school = personInfo.graduate_school; person_Info.graduate_year = personInfo.graduate_year; person_Info.contact_tel = personInfo.contact_tel; misInfoEntities.Entry<person_info>(person_Info).State = EntityState.Modified; return misInfoEntities.SaveChanges(); }
没什么可说的,很简单,今天就到这里,我还没写完呢,就被评为推荐,在此谢过,收拾上班。