"如何系列" 关于 MVC、jQuery、JSON、分页、mapRoute






4.91/5 (85投票s)
"如何系列" 关于 MVC、jQuery、JSON、分页、mapRoute。
引言
由于数据库系统中有大量数据,客户端工作变得非常重要。在传统的 ASP.NET 中,代码隐藏的自然方法是使用 ASP.NET 组件在代码隐藏文件中编写大部分工作。此外,ASP.NET 组件的渲染和视图状态机制现在被认为是经典 ASP.NET 的薄弱之处。
因此,出现了一种新的范例。根据这种新范例,开发人员可以处理纯 HTML 和 JavaScript,减少渲染并避免影响性能的视图状态。
尽管 MVC 被认为是一种古老的设计或架构模式,但它尤其在提到上述经典 ASP.NET 的瓶颈之后而变得流行。在 MVC 中有效利用 jQuery 和 JSON 可以开发出高性能的应用程序。
背景
在阅读了一些关于 MVC、jQuery 和 JSON 的初级文章后,本文可能会有所帮助。以下链接可能对初学者有用:
- MVC 入门: https://w3schools.org.cn/aspnet/mvc_intro.asp
- jQuery 入门: https://w3schools.org.cn/jquery/default.asp
- JSON 入门: https://w3schools.org.cn/json/default.asp
使用代码
本文旨在提供一个“如何系列”。因此,所有脚本都来自附加的源代码。事实上,每个“如何”都可以成为一篇独立的文章。无论如何,所有可能的答案都收集在一个示例中。本文中的实际方法多于理论知识。为了简化示例,使用了一些静态列表而不是数据库。
以下问题将得到解答:
- 如何在 MVC 中实现高性能的 CRUD 操作?
- 如何使用 jQuery 对话框代替 JavaScript 的 confirm 或 alert?
- 如何在 MVC 列表中实现分页?
- 如何在 MVC 中使用“显示更多”链接?
- 如何在链接中使用属性?
- 如何在 jQuery 中进行 AJAX 调用?
- 如何在 MVC 中使用 Form collection?
- 如何一次删除多条记录?
- 如何在 MVC 中使用部分视图操作(partial action)?
- 如何在 MVC 应用程序中使用 JSON 格式?
- 如何填充主从组合框(master-detail combobox)?
- 如何使用 jQuery datepicker?
- 如何在 MVC 中使用 jQuery 对话框上传图片?
- 如何在客户端创建表格行?
- 如何自定义 `Global.asax` 中的 `mapRoute`?
- 如何实现表格行的全选和全不选
- 如何显示“正在加载数据”
- 如何使用 jQuery 创建主从表格(master-detail grids)?
1) 如何在 MVC 中实现高性能的 CRUD 操作?
粗略考虑,所有业务解决方案都具有创建-读取-更新-删除(CRUD)的特性。如果可能,从开发者的角度来看,为“插入”和“更新”使用相同的“保存表单”可能更具成本效益。通过管理发送到操作的参数,可以使用相同的表单。
假设你有一个类似表格的列表,实际上是一个 HTML 表格,并在表单上有一个单独的“新建”按钮。在表格的每一行中,都有一个与该行相关的“编辑”和“删除”按钮。
点击“新建”后,重定向到一个新页面——这里称为视图——并不是一个有效的方法。因为在重定向页面上保存数据后,用户必须点击“显示列表”才能看到插入到数据库中的数据。这意味着重定向列表视图并以可变的查询成本从数据库中选择数据!
而不是上面描述的“点击新建,然后再次列出”的场景,可以执行更好的方法。
Create(创建):
- 在列表视图中,点击“新建”后,会出现一个“jQuery 保存对话框”。
- Create 视图被渲染到 jQuery 对话框中。
- 填写 Create 表单并点击“保存”。
- 在点击保存按钮时,可以通过 AJAX POST 将数据发送到相关控制器。
- Ajax 表单有一个 `onSuccess` JavaScript 函数。
- 在“`onSuccess`”JavaScript 方法中,添加的新行(作为传递给“`onSuccess`”的参数 JSON)会被插入到列表中,而无需刷新整个列表。
Read(读取):
这是一个列表操作。如果可能,列表表单上应只显示所需数据。可以使用以下技术:
- 通过组合框或数字进行分页,
- 实现“显示更多”
- 带有过滤条件的列表。
Update(更新):
- 在列表视图中,点击列表中任意行的“编辑”后,会出现相同的“jQuery 保存对话框”,并显示选中行的数据。
- 因为所有步骤都与“创建”相同,所以只需要根据“更新”操作修改“`onSuccess`”方法。
- 在这种情况下,在数据库更新后,视图中只有被编辑的行的数据会被更新。通过这种方式,无需刷新整个列表即可查看最近编辑的记录。
Delete(删除):
- 在用一个漂亮的 jQuery 对话框确认后,在数据库删除后,只有选中行会从列表中移除。同样,无需刷新整个列表。
同一个对话框用于插入和编辑。
链接在 `PersonList.cshtml` 视图中如下:
@Html.ActionLink("New", "Save",
new { personNo = 0 }, new { @class = "newLink" })
...
@Html.ActionLink("Edit", "Save", new { personNo = item.PersonNo }, new { @class = "editLink" })
- New:要显示的文本。
- Save:控制器中的操作。
- personNo :作为参数传递给“Save”操作。** 如果为 0,则对话框将为空;如果大于 0,则在对话框中显示该 ID 的数据。
- newLink:在下面的 jQuery 中使用的虚构类名。
<div id="saveDialog" title="Person Information"></div>
<script type="text/javascript">
var linkObj;
//.....
$(document).ready(function () {
//...
$('#saveDialog').dialog({
autoOpen: false,
width: 400,
resizable: false,
modal: true,
buttons: {
"Save": function () {
$("#update-message").html('');
$("#savePersonForm").submit();
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
//....
setLinks();
});
// ....
function setLinks()
{
$(".editLink, .newLink, uploadPicLink").unbind('click');
$(".editLink, .newLink").click
(
function ()
{
linkObj = $(this);
var dialogDiv = $('#saveDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data)
{
dialogDiv.html(data);
//validation
var $form = $("#savePersonForm");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
$form.validate($form.data("unobtrusiveValidation").options);
dialogDiv.dialog('open');
});
return false;
}
);
//...
} //end setLinks
</script>
`PersonController` 中的 Save 操作如下:
// ...
[HttpGet]
public ActionResult Save(int personNo)
{
Person person= new Person();
person.BirthDate = DateTime.Today;
person.PersonNo = 0;
if (personNo > 0)
{
person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
}
return PartialView(person);
}
// ...
[HttpPost]
public JsonResult Save(Person p)
{
//...
}
// ...
2) 如何使用 jQuery 对话框代替 JavaScript 的 confirm 或 alert?
在 Windows 应用程序中可以使用自定义的消息框。对于 Web,可以使用第三方组件库来实现。也可以使用 jQuery 对话框代替 JavaScript 的对话框,如下所示:
`PersonList` 视图中的 Delete 链接如下:
@Html.ActionLink("Delete", "DeletePerson", new { personNo =
item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })
HTML 和 jQuery 代码如下:
<div id="confirmDialog" title="Warning"></div>
<script type="text/javascript">
//...
$(".deleteLink").live("click", function (e) {
e.preventDefault();
// ..
$("#confirmDialog").html('<br/><br/>sure?');
$("#confirmDialog").dialog({
resizable: false,
height: 200,
width: 300,
modal: true,
buttons: {
"Yes": function () {
// ..
}, // end of yes button
"No": function () {
$(this).dialog("close");
}
} //end buttons
}); //end modal
}); //end delete
//...
</script>
3) 如何在 MVC 列表中实现分页?
分页是列出数据和最小化数据传输成本的良好方法之一。可以执行许多显示数据的方法。在本“如何”中,使用组合框进行分页。但是,如果需要,可以在页面底部显示数字。这取决于应用程序和开发人员。可以使用组合框进行分页,如下所示:
首先,为分页元数据安排好位置,如下所示:
@model AddressBook_mvc3_jQuery.Models.Paginginfo
...
<div id="paginginfo">
<hr />
<select id="PageSelect"></select>
<span class="pagingPersonNo" style="visibility:hidden">@Model.id</span>
<span class="pagingTotalCount" style="visibility:hidden">@Model.TotalCount</span>
<span class="pagingPageSize" style="visibility:hidden">@Model.PageSize</span>
<span class="pagingSummary">aaa</span>
<hr/>
</div>
<div id="content"></div>
...
在页面首次加载时,使用以下脚本填充 ID 为“`paginginfo`”的 div 并显示第一页记录:
<script type="text/javascript">
//...
function initializePaging()
{
var PersonNo = $("#paginginfo .pagingPersonNo").text();
var TotalCount = $("#paginginfo .pagingTotalCount").text();
var PageSize = $("#paginginfo .pagingPageSize").text();
var PageSelect = $("#PageSelect");
if (TotalCount==0)
{
PageSelect.html("");
$("#paginginfo").hide();
}
else
{
PageSelect.html("");
var num = Math.ceil(TotalCount/PageSize);
for (var i = 1; i <= num; i++)
{
if (i==1)
PageSelect.append($("<option selected></option>").val(i).text(i));
else
PageSelect.append($("<option></option>").val(i).text(i));
}
}
fillData(PersonNo, 1);
}
//..
function fillData(parPersonNo, parPageNo)
{
if (parPageNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetAddressList", "Address")",
data: { personNo: parPersonNo, pageNo: parPageNo },
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#content").html(data.Html);
buttonizeALL();
setLinkAbilites();
setPagingSummary(parPageNo);
}
else
{
alert('opps!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
} // if (parPageNo)
}//fillData
//...
</script>
控制器中的操作代码如下。可以看到,结果列表被部分渲染并使用 `RenderPartialView` 方法放入 JSON 对象中。
public class AddressController : Controller
{
//..
public JsonResult GetAddressList(int personNo, int pageNo)
{
int pageSize = 5; //it could be parameter
int skipCnt = ((pageNo - 1) * pageSize);
List<Address> list = (from x in Repository.GetAddressList() where x.PersonNo ==
personNo orderby x.AddressNo descending select x).Skip(skipCnt).Take(pageSize).ToList();
JsonResult jr = Json(new
{
Html = this.RenderPartialView("AddressList", list),
Message = "OK"
}, JsonRequestBehavior.AllowGet);
return jr;
}
//..
}
当 ID 为“`PageSelect`”的组合框的 `selecteditem` 发生变化时,将运行以下 jQuery 脚本:
//..
$("#PageSelect").change(function ()
{
var $this = $(this);
var parPageNo = $this.val();
var parPersonNo = $("#paginginfo .pagingPersonNo").text();
fillData(parPersonNo,parPageNo);
});//PageSelect
//..
4) 如何使用 jQuery 实现“显示更多”链接?
这项技术在许多流行的网站中都有使用。它应该在大列表上执行。“显示更多”可以按如下方式实现:
列表视图有一个“更多”链接。
//
<table id="NoteTable"></table>
<br />
<a href="#" style="display:none" id="more">more</a>
<div id="saveDialog" title="Notes Information"></div>
<div id="confirmDialog" title="Warning"></div>
//
点击“更多”后,将运行以下 jQuery 脚本:
//..
//load more results
$(function ()
{
$("#more").click(function (e)
{
e.preventDefault();
var lastNoteNo = $("#NoteTable tr:last .noteNo").text();
if (lastNoteNo)
{
var PersonNo = $("#paginginfo .pagingPersonNo").text();
fillData(PersonNo, lastNoteNo);
}
//--- scroll to bottom of page ---
var $target = $('html,body');
$target.animate({scrollTop: $target.height()}, "slow");
//--- /scroll to bottom of page ---
return false;
});
});
//..
function fillData(parPersonNo, parLastNoteNo)
{
if (parPersonNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetNoteList", "Note")",
data: { personNo: parPersonNo, lastNoteNo: parLastNoteNo} ,
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#NoteTable").append(data.Html);
buttonizeALL();
setLinkAbilites();
if (data.HasMore)
$("#more").show();
else
$("#more").hide();
}
else
{
alert('opps!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
} // if
}//func
// ..
控制器中的以下操作返回 JSON 结果:
public class NoteController : Controller
{
//...
public JsonResult GetNoteList(int personNo, int lastNoteNo)
{
int pageSize = 5; //it could be parameter
bool hasMore = false;
List<Note> list = null;
if (lastNoteNo == 0)
{
list = (from x in Repository.GetNoteList() where x.PersonNo == personNo
orderby x.NoteNo descending select x).Take(pageSize).ToList();
hasMore = (from x in Repository.GetNoteList() where x.PersonNo ==
personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
}
else
{
list = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo &&
x.PersonNo == personNo orderby x.NoteNo descending select x).Take(pageSize).ToList();
hasMore = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo &&
x.PersonNo == personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
}
JsonResult jr = Json(new
{
Html = this.RenderPartialView("_NoteList", list),
Message = "OK",
HasMore = hasMore
}, JsonRequestBehavior.AllowGet);
return jr;
}
// ...
}
5) 如何在链接中使用属性?
这是一种很好的能力,尤其适用于按钮,例如编辑、删除、显示详情等。
在创建列表时,将相关键作为属性附加到链接。点击链接事件时,可以使用该键轻松完成操作。
例如,假设列表中的每一行都有一个删除链接。当点击行中的删除链接时,可以使用该键作为控制器中“删除操作”的参数。
@Html.ActionLink("Delete", "DeletePerson", new { personNo = item.PersonNo },
new { @class = "deleteLink", @pkNo = item.PersonNo })
在客户端检查源代码时,会看到以下行:
<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
href="https://codeproject.org.cn/Person/DeletePerson/1" pkno="1"><span class="ui-button-text">Delete</span></a>
在 jQuery 脚本中,属性的使用如下。例如,pkno 为 1 并被使用。
$(".deleteLink").live("click", function (e)
{
e.preventDefault();
var pkNo = $(this).attr("pkNo");
//..
});
6) 如何在 jQuery 中进行 AJAX 调用?
AJAX 调用是提高应用程序速度的一个非常好的能力。在一些数据库数据量大的应用程序中,开发人员必须注意两条数据线上的低数据传输量。第一条线是数据库和应用程序之间,第二条线是应用程序和客户端浏览器之间。对于这类需求,AJAX 调用非常有用。
//..
$.ajax({
type: "POST",
url: "/Person/DeletePerson",
data: { personNo: pkNo },
cache: false,
dataType: "json",
success: function ()
{
//..
},
error: function (jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
//..
URL 也可以像这样使用:
//..
url: "@Url.Action("DeletePerson", "Person")",
// ..
7) 如何在 MVC 中使用 Form collection?
提交表单时,所有表单元素都作为集合发送到控制器中的相关操作。
在控制器中,可以使用每个键值对。假设你有一个如下的保存表单:
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text" name="TBPersonNo"
id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text" name="TBAddressNo"
id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
视图中的数据可以作为模型对象或 FormCollection 提交到控制器中的操作,如下所示:
//..
[HttpPost]
public JsonResult Save(FormCollection fc)
{
object obj = null;
Address addrTmp = new Address();
addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
addrTmp.AddressText = fc["TBAddressText"].ToString();
addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString());
if (ModelState.IsValid)
{
if (addrTmp.AddressNo == 0)
{
//find last person
//if it is database system no need to this line. Probably the AddressNo would be autoincrement
addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;
Data.Repository.GetAddressList().Add(addrTmp);
obj = new { Success = true,
Message = "Added successfully",
Object = addrTmp,
operationType = "INSERT",
Html = this.RenderPartialView("_addressLine", addrTmp )
};
}
else
{
Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
addr.AddressTypeNo = addrTmp.AddressTypeNo;
addr.AddressText = addrTmp.AddressText;
addr.CityNo = addrTmp.CityNo;
addr.PersonNo = addrTmp.PersonNo;
obj = new { Success = true,
Message = "Updated successfully",
Object = addr,
operationType = "UPDATE",
Html = this.RenderPartialView("_addressLine", addr )
};
}
}
else
{
obj = new { Success = false, Message = "Please check form" };
}
return Json(obj, JsonRequestBehavior.DenyGet);
}
//..
8) 如何一次删除多条记录?
在某些页面上,一次删除多条记录有时可以使业务更容易。通过收集所有选定记录的键,可以删除多条记录。将所有键发送到控制器后,可以按如下方式执行删除:
首先点击带有“`deleteALL`”ID 的“Delete Selected”按钮。点击“Yes”后,可以使用以下 jQuery 脚本。当然,也可以开发替代脚本。
//..
$("#deleteALL").live("click", function (e)
{
e.preventDefault();
var len = $("#NoteTable tr").length;
$("#confirmDialog").html('<br/><br/>deleting all selecteds.. sure?');
$("#confirmDialog").dialog({
resizable: false,
height: 200,
width: 300,
modal: true,
buttons:
{
"Yes": function ()
{
$(this).dialog("close");
var strSelecteds = '';
var rows = $("#NoteTable tr");
for(var i=0; i< rows.length; i++)
{
var row = $(rows).eq(i);
var span = row.find('span#cboxSpan');
var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
var checked=(cb.is(':checked'));
var pkno = cb.attr("pkno");
if (checked)
{
strSelecteds = strSelecteds + pkno + ',';
}
}//
if (strSelecteds.length>0)
{
strSelecteds = strSelecteds.substring(0,strSelecteds.length-1);
}
if (strSelecteds.length>0)
{
$.ajax({
type: "POST",
url: "/Note/DeleteALL",
data: { noteNOs: strSelecteds },
cache: false,
dataType: "json",
success: function (data)
{
var strSelectedsArr = strSelecteds.split(',');
for (var i = 0; i < strSelectedsArr.length; i++)
{
var rowNo = '#row-' + strSelectedsArr[i];
$(rowNo).remove();
//alert(strSelectedsArr[i]);
}//for
$('#saveDialog').dialog('close');
$('#Message').html(data.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);
},
error: function(jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
}
else
alert('No row selected');
}, // end of yes button
"No": function ()
{
$(this).dialog("close");
}
} //end buttons
}); //end modal
}); //end deleteALL
//...
如上所示,通过 AJAX 调用“Note”控制器中的“DeleteALL”操作,可以删除多条记录。
9) 如何在 MVC 中使用部分视图操作(partial action)?
在某些情况下,需要在多个表单上使用一个组件。例如,你可能需要在一些单独的表单上有一个“人员信息框”,如下所示:
`_personinfo` 视图可以如下:
@model AddressBook_mvc3_jQuery.Models.Person
@{ ViewBag.Title = "_personinfo"; }
<fieldset>
<legend>Person info</legend>
<table>
<tr><td><b><span> @Model.FirstName @Model.LastName </span></b>(@String.Format("{0:dd.MM.yyyy}",
Model.BirthDate))</td><td>(@Model.CategoryName)</td></tr>
</table>
</fieldset>
在任何视图中使用部分视图操作,可以使用以下代码行:
//..
<h2>Address List</h2>
<div>
@Html.Action("_personinfo", "Common")
</div>
//..
10) 如何在 MVC 应用程序中使用 JSON 格式?
在向控制器操作发送参数和从操作获取结果时,可以使用 JSON 格式。如下所示,Note 控制器中的 DeleteNote 操作有一个 noteNo 参数。这里,pkNo 是一个值传递参数。
$(".deleteLink").live("click", function (e)
{
e.preventDefault();
var pkNo = $(this).attr("pkNo");
//..
$.ajax({
type: "POST",
url: "/Note/DeleteNote",
data: { noteNo: pkNo },
cache: false,
dataType: "json",
success: function ()
{
$(rowNo).remove();
},
error: function(jqXHR, exception)
{
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}); //end ajax call
//..
}); //end delete
可以从控制器操作获取 JSON 结果。以下脚本以 JSON 对象的形式返回结果:
//..
[HttpPost]
public JsonResult DeleteNote(int noteNo)
{
string message = string.Empty;
try
{
Note n = Data.Repository.GetNoteList().Where(c => c.NoteNo == noteNo).FirstOrDefault();
if (n != null)
{
Data.Repository.GetNoteList().Remove(n);
message = "Deleted";
}
else
{
message = "Note not found!";
}
}
catch (Exception ex)
{
message = ex.Message;
}
return Json(new { Message = message }, JsonRequestBehavior.AllowGet);
}
//..
11) 如何填充主从组合框(master-detail combobox)?
某些表单要求在更改一个组合框时填充另一个组合框。例如,对于国家-城市对,国家可以被认为是主,城市是次。
“保存表单”视图中的 HTML 如下:
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text" name="TBPersonNo"
id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text" name="TBAddressNo"
id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
首次加载时,使用 Address 控制器中的“GetCountryList”操作填充 idCBCountry 组合框。然后,在更改国家组合框时,按如下方式填充城市组合框:
<script type="text/javascript">
$(document).ready(function () {
//...
//-----------------------------------------------------
$.ajax({
type: "POST",
url: "@Url.Action("GetCountryList", "Address")",
data: {},
cache: false,
dataType: "json",
success: function (data)
{
var idCBcountry = $("#idCBcountry");
idCBcountry.html("");
if (@Model.AddressNo>0)
{
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (item.CountryNo == @Model.CountryNo)
{
idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
fillCity(item.CountryNo);
}
else
{
idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
}
} //for
}
else
{
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (i==0)
{
idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
fillCity(item.CountryNo);
}
else
{
idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
}
} //for
}//else
},
error: function(exp)
{
alert('ErrorCountry : ' + exp.responseText);
}
});
//-----------------------------------------------------
$("#idCBcountry").change(function () {
var $this = $(this);
var CountryNo = $this.val();
if (CountryNo)
{
fillCity(CountryNo);
}//if
});
//-----------------------------------------------------
});//end of function
function fillCity(parCountryNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCityList", "Address")",
data: {CountryNo: parCountryNo},
cache: false,
dataType: "json",
success: function (data)
{
var idCBcity = $("#idCBcity");
idCBcity.html("");
for (var i = 0; i < data.List.length; i++)
{
var item = data.List[i];
if (item.CityNo == @Model.CityNo)
{
idCBcity.append($("<option selected></option>").val(item.CityNo).text(item.CityName));
}
else
{
idCBcity.append($("<option />").val(item.CityNo).text(item.CityName));
}
}
},
error: function(exp)
{
alert('ErrorCity : ' + exp.responseText);
}
});
}//fillCity
</script>
操作代码如下。列表被嵌入到 JSON 对象中。然后,在上面显示的 jQuery 脚本中,列表元素使用索引来访问。
public class AddressController : Controller
{
//..
public JsonResult GetCountryList()
{
object obj = null;
List<Country> list = Repository.GetCountryList();
obj = new { Success = true, Message = "OK", List = list };
return Json(obj, JsonRequestBehavior.AllowGet);
}
public JsonResult GetCityList(int CountryNo)
{
object obj = null;
List<City> list = Repository.GetCityList().Where(c => c.CountryNo == CountryNo).ToList(); ;
obj = new { Success = true, Message = "OK", List = list };
return Json(obj, JsonRequestBehavior.AllowGet);
}
//..
}
此技术可用于视图表单上的任何 HTML 元素。
12) 如何使用 jQuery datepicker?
日期类型几乎用于所有业务应用程序。由于文化差异,有时使用此类型会对开发人员造成麻烦。但是,jQuery datepicker 使日期类型的处理变得容易。
要在列表中以所需格式显示日期,可以使用以下行:
<span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>
在保存表单中,使用以下 HTML 脚本:
...
<div class="editor-label">
@Html.LabelFor(model => model.BirthDate)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.BirthDate,
new { @class = "BirthDateSave",
@id = "TBBirthDate",
@Value = Model.BirthDate.ToString("dd.MM.yyyy")
})
</div>
...
jQuery Datepicker 可以与 @Html.TextboxFor 一起使用,使用同一页面上的以下脚本:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$(".BirthDateSave").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'dd.mm.yy',
showOn: 'both'
});
});
</script>
必须在适当的 .cshtml 文件开头包含以下行:
..
<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
..
13) 如何在 MVC 中使用 jQuery 对话框上传图片?
可以在单独的视图中轻松上传图片。但是,仅为上传图片而重定向到单独的视图,然后再次重定向到列表视图,从成本角度来看可能效率低下。因此,相反,在列表视图中,可以通过点击每行的上传链接打开一个 jQuery 对话框,然后浏览并上传图片。
点击“Upload Pic”后,将运行以下脚本:
//..
$(".uploadPicLink").click
(
function ()
{
linkObj = $(this);
var dialogDiv = $('#savePicDialog');
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data) {
dialogDiv.html(data);
//validation
var $form = $("#savePersonPicForm");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
$form.validate($form.data("unobtrusiveValidation").options);
dialogDiv.dialog('open');
});
return false;
}
);
//..
加载到 jQuery 对话框中的 SavePersonPic 表单如下。iframe 用于在 jQuery 对话框中上传文件。
@model AddressBook_mvc3_jQuery.Models.Person
@{ViewBag.Title = "Save image";}
@using (Html.BeginForm("SavePersonPic", "Person", FormMethod.Post,
new
{
enctype = "multipart/form-data",
id = "savePersonPicForm",
name = "savePersonPicForm",
target = "UploadTarget"
}))
{
@Html.ValidationSummary(true)
<div id="update-message" class="error invisible"></div>
<fieldset>
<legend>Person Picture</legend>
<div class="editor-label">
<label for="file">Upload Image:</label>
</div>
<div class="editor-field">
<input type="file" name="file" id="file"/>
</div>
</fieldset>
}
<iframe id="UploadTarget"
name="UploadTarget" onload="UploadImage_Complete();"
style="position: absolute; left: -999em; top: -999em;">
</iframe>
控制器中用于上传文件的操作如下:
public class PersonController : Controller
{
//..
//-------------- image -----
[HttpGet]
public ActionResult SavePersonPic(int personNo)
{
Person person = new Person();
if (personNo > 0)
{
person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
}
return PartialView(person);
}
[HttpPost]
public JsonResult SavePersonPic(HttpPostedFileBase file, int personNo)
{
string message = string.Empty;
bool success = false;
string imgPath = "";
string fileName = "";
try
{
string path = System.IO.Path.Combine(Server.MapPath("~/Content/images"),
System.IO.Path.GetFileName(file.FileName));
file.SaveAs(path);
Person p = Data.Repository.GetPersonList().Where(r => r.PersonNo == personNo).FirstOrDefault();
p.imgFileName = file.FileName;
ViewBag.Message = "File uploaded successfully";
message = ViewBag.Message;
fileName = file.FileName;
imgPath = Url.Content(String.Format("~/Content/images/{0}", fileName));
success = true;
}
catch (Exception ex)
{
message = ex.Message;
success = true;
imgPath = "";
fileName = "";
}
return Json(
new { Success = success,
Message = message,
PersonNo=personNo,
ImagePath = imgPath,
FileName = fileName
},
JsonRequestBehavior.AllowGet
);
}
//------------- /image --------
// ..
}
iframe 的 JavaScript “onload”函数如下。上传的图片会在列表的相应行中显示,而无需刷新该行。
//..
function UploadImage_Complete()
{
//Check first load of the iFrame
if (isFirstLoad == true)
{
isFirstLoad = false;
return;
}
try
{
//Reset the image form
document.getElementById("savePersonPicForm").reset();
var jsonTxt = ($('#UploadTarget').contents()).text();
var jsonObj = JSON.parse(jsonTxt);
var rowid = '#row-' + jsonObj.PersonNo;
var row = $('#personTable ' + rowid);
var imgid = "#img-" + jsonObj.PersonNo;
var img = row.find(imgid);
$(img).attr("src", jsonObj.ImagePath);
$('#Message').html(jsonObj.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300)
$('#savePicDialog').dialog('close');
}
catch (err)
{
alert(err.get_Message());
}
}
//..
14) 如何在客户端创建表格行?
添加到数据库的记录应该在客户端的列表中显示。这可以通过多种方式完成。添加记录后,可以从数据库完全刷新列表,但这会导致繁重的操作。然而,使用 JavaScript 或 jQuery,可以在不刷新视图上的所有元素的情况下,将新行添加到列表中。这里提到了两种方法。
第一种方法,即逐行逐单元格地由 JavaScript 创建行和单元格,如下所示。从下面的脚本可以看出,在提交此表单后,使用 **saveSuccess** JavaScript 函数来处理这种情况:
..
@model AddressBook_mvc3_jQuery.Models.Person
@{ ViewBag.Title = "Save Person"; }
..
@using (Ajax.BeginForm("Save", "Person", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "savePersonForm" }))
{
@Html.ValidationSummary(true)
..
}
..
**saveSuccess** JavaScript 方法如下。操作返回一个包含操作类型的 JSON 结果。根据操作(INSERT 或 UPDATE),会修改视图上的表格。当一条新记录添加到数据库时,新的一行会被添加到表格的开头。当一条现有记录在数据库中被更新时,表格中只有相关的行会被修改。
..
function saveSuccess(data)
{
if (data.Success == true)
{
if (data.operationType == 'UPDATE')
{
//we update the table's row info
var parent = linkObj.closest("tr");
$(parent).animate({ opacity: 0.3 }, 200, function () {;});
parent.find(".FirstName").html(data.Object.FirstName);
parent.find(".LastName").html(data.Object.LastName);
parent.find(".CategoryName").html(data.Object.CategoryName);
var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
var dateStr = FormatDate(date);
parent.find(".BirthDate").html(dateStr);
$(parent).animate({ opacity: 1.0 }, 200, function () {;});
}
else
{ //INSERT
//we add the new row to table
//we do not refresh all records on screen
try
{
var personTable = document.getElementById("personTable");
var row = personTable.insertRow(1); //row 0 is header
row.setAttribute("id", 'row-' + data.Object.PersonNo.toString());
var buttonsLinks =
'<a role="button" class="editLink ui-button ui-widget ui-state-default ui-corner-all ' +
'ui-button-text-only ui-state-hover ui-state-focus" href="https://codeproject.org.cn/Person/Save/' +
data.Object.PersonNo.toString() + '"><span class="ui-button-text">Edit</span></a> ' +
'<a role="button" class="adressLink ui-button ui-widget ui-state-default ui-corner-all ' +
'ui-button-text-only" href="https://codeproject.org.cn/Address/Index/' + data.Object.PersonNo.toString() +
'"><span class="ui-button-text">Addresses</span></a> ' +
'<a role="button" class="noteLink ui-button ui-widget ui-state-default ui-corner-all ' +
'ui-button-text-only" href="https://codeproject.org.cn/Note/Index/' + data.Object.PersonNo.toString() +
'"><span class="ui-button-text">Notes</span></a> ' +
'<a role="button" class="deleteLink ui-button ui-widget ui-state-default ' +
'ui-corner-all ui-button-text-only" href="https://codeproject.org.cn/Person/Delete/' +
data.Object.PersonNo.toString() + '" pkno="' + data.Object.PersonNo.toString() +
'"><span class="ui-button-text">Delete</span></a>';
var cellButtons = row.insertCell(0);
cellButtons.innerHTML = buttonsLinks;
var cellPersonNo = row.insertCell(1);
cellPersonNo.innerHTML = "<span class=\"PersonNo\">" +
data.Object.PersonNo + "</span>";
var cellCategoryName = row.insertCell(2);
cellCategoryName.innerHTML = "<span class=\"CategoryName\">" +
data.Object.CategoryName + "</span>";
var cellFN = row.insertCell(3);
cellFN.innerHTML = "<span class=\"FirstName\">" +
data.Object.FirstName + "</span>";
var cellLN= row.insertCell(4);
cellLN.innerHTML = "<span class=\"LastName\">" +
data.Object.LastName + "</span>";
var cellBirthDate = row.insertCell(5);
var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
var dateStr = FormatDate(date);
cellBirthDate.innerHTML = "<span class=\"BirthDate\">" +
dateStr + "</span>";
var cellimgFileName = row.insertCell(6);
cellimgFileName.innerHTML =
"<img id=\"img-" + data.Object.PersonNo.toString() + "\" alt=\"" +
data.Object.ImgFileName + "\" src=\"/content/images/" + "noimg.jpg" +
"\" height=\"35px\" width=\"50px\"><br><a " +
"class=\"uploadPicLink\" href=\"/Person/SavePersonPic/" + data.Object.PersonNo.toString() +
"\" pkno=\"" + data.Object.PersonNo.toString() +
"\" style=\"font-size:9px;\">Upload Pic</a>";
setLinks();
}
catch (err) {
alert(err.Message);
}
}
$('#saveDialog').dialog('close');
$('#Message').html(data.Message);
$('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);
}
else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}
..
表格如下:
//..
<table id="personTable">
<tr>
<th></th>
<th>
#
</th>
<th>
Category
</th>
<th>
FirstName
</th>
<th>
SecondName
</th>
<th>
BirthDate
</th>
<th>
image
</th>
</tr>
@foreach (var item in Model) {
<tr id="row-@item.PersonNo">
<td>
@Html.ActionLink("Edit", "Save",
new { personNo = item.PersonNo }, new { @class = "editLink" })
@Html.ActionLink("Addresses", "Index",
"Address", new { personNo = item.PersonNo }, new { @class = "adressLink" })
@Html.ActionLink("Notes", "Index",
"Note", new { personNo = item.PersonNo }, new { @class = "noteLink" })
@Html.ActionLink("Delete", "DeletePerson",
new { personNo = item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })
</td>
<td>
<span class="PersonNo">@item.PersonNo</span>
</td>
<td>
<span class="CategoryName">@item.CategoryName</span>
</td>
<td>
<span class="FirstName">@item.FirstName</span>
</td>
<td>
<span class="LastName">@item.LastName</span>
</td>
<td>
<span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>
</td>
<td>
<img id="img-@item.PersonNo" height="35px" width="50px"
alt="@item.ImgFileName " src="https://codeproject.org.cn/content/images/@item.ImgFileName" />
<br />
@Html.ActionLink("Upload Pic", "SavePersonPic", new { personNo = item.PersonNo },
new { @class = "uploadPicLink", @pkNo = item.PersonNo, style = "font-size:9px;" })
</td>
</tr>
}
</table>
//..
上面提到的第一种方法可能看起来是一种旧的方法。因此,以下**第二种方法**可能更可行。在这种方法中,使用渲染的 HTML 来添加或更新表格行。假设有一个如下的表格:
@model IEnumerable<AddressBook_mvc3_jQuery.Models.Address>
<table id="AddressTable">
<tr>
<th></th>
<th>
#
</th>
<th>
AddressType
</th>
<th>
City/Country
</th>
<th>
Address Text
</th>
</tr>
@foreach (var item in Model)
{
<tr id="row-@item.AddressNo">
<td>
@Html.ActionLink("Edit", "Save",
new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
@Html.ActionLink("Delete", "DeleteAddress",
new { addressNo = item.AddressNo }, new { @class = "deleteLink", @pkNo = item.AddressNo })
</td>
<td>
<span class="AddressNo">@item.AddressNo</span>
</td>
<td>
<span class="AddressTypeName">@item.AddressTypeName</span>
</td>
<td>
<span class="CityName">@item.CityName/@item.CountryName</span>
</td>
<td>
<span class="AddressText">@item.AddressText</span>
</td>
</tr>
}
</table>
点击“新建”后,以下脚本会加载到一个 jQuery 对话框中:
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "saveSuccess"
}, new { @id = "saveForm" }))
{
@Html.ValidationSummary(true)
<input style="visibility:hidden" type="text"
name="TBPersonNo" id="idTBPersonNo" value="@Model.PersonNo"/>
<input style="visibility:hidden" type="text"
name="TBAddressNo" id="idTBAddressNo" value="@Model.AddressNo"/>
<br />
<fieldset>
<table>
<tr>
<td>Address Type</td>
<td>
<select name="CBAddressType" id="idCBAddressType" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<select name="CBcountry" id="idCBcountry" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>City</td>
<td>
<select name="CBcity" id="idCBcity" style="width:120px">
</select>
</td>
</tr>
<tr>
<td>AddressText</td>
<td>
<textarea rows="4" cols="25" name="TBAddressText"
id="idTBAddressText">@Model.AddressText</textarea>
</td>
</tr>
</table>
</fieldset>
}
当表单提交时,将运行控制器中的以下操作:
public class AddressController : Controller
{
//..
[HttpPost]
public JsonResult Save(FormCollection fc)
{
object obj = null;
Address addrTmp = new Address();
addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
addrTmp.AddressText = fc["TBAddressText"].ToString();
addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString());
if (ModelState.IsValid)
{
if (addrTmp.AddressNo == 0)
{
//find last person
//if it is database system no need to this line. Probably the AddressNo would be autoincrement
addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;
Data.Repository.GetAddressList().Add(addrTmp);
obj = new { Success = true,
Message = "Added successfully",
Object = addrTmp,
operationType = "INSERT",
Html = this.RenderPartialView("_addressLine", addrTmp )
};
}
else
{
Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
addr.AddressTypeNo = addrTmp.AddressTypeNo;
addr.AddressText = addrTmp.AddressText;
addr.CityNo = addrTmp.CityNo;
addr.PersonNo = addrTmp.PersonNo;
obj = new { Success = true,
Message = "Updated successfully",
Object = addr,
operationType = "UPDATE",
Html = this.RenderPartialView("_addressLine", addr )
};
}
}
else
{
obj = new { Success = false, Message = "Please check form" };
}
return Json(obj, JsonRequestBehavior.DenyGet);
}
// ..
}
`RenderPartialView` 方法用于获取所需的 HTML 脚本。
//..
public static string RenderPartialView(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext,
viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
//..
saveAddress 表单中 AJAX POST 的 saveSuccess 函数如下:
<script type="text/javascript">
//...
function saveSuccess(data)
{
if (data.Success == true)
{
$("#paginginfo").show();
if (data.operationType == 'UPDATE')
{
var row = linkObj.closest("tr");
// the following line can also be used to get related row
//$('#AddressTable #row-' + data.Object.AddressNo);
row.replaceWith(data.Html);
//..
}
else
{ //INSERT
try
{
$("#AddressTable tr:first").after(data.Html);
//..
}
catch (err)
{
alert(err.Message);
}
}
//..
}
else
{
//..
}
}
//..
</script>
上述两种技术中的任何一种都可以使用。
15) 如何自定义 `Global.asax` 中的 `mapRoute`?
在经典的 ASP.NET 应用程序中,URL 重写操作可以通过一些第三方程序集轻松完成。在 MVC 应用程序中,可以使用 `Global.asax` 来自定义 `mapRoutes`。
`Global.asax` 中的默认 maproute 如下:
public class MvcApplication : System.Web.HttpApplication
{
//..
public static void RegisterRoutes(RouteCollection routes)
{
// all new customized maproute rules can be put here
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
// ..
}
根据以下脚本,**`/Save/{addressNo}/{personNo}`** 被用作链接。
@Html.ActionLink("Edit", "Save",
new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
上面链接的快照如下:
因此,可以在 `Global.asax` 中添加一个自定义的 maproute 规则,如下所示:
//..
routes.MapRoute(
"AddressSave",
"Address/Save/{addressNo}/{personNo}",
new { controller = "Address", action = "Save",
addressNo = UrlParameter.Optional, personNo = UrlParameter.Optional }
);
//..
上述两种技术中的任何一种都可以使用。
16) 如何实现表格行的全选和全不选?
在许多应用程序中,有时需要一次性选中或取消选中表格中的所有复选框,如下所示:
可以使用以下脚本来实现这样的功能:
..
<br />
| <a href="#" class="checkALLRecords" id="checkALL">Check ALL</a> | <a href="#" class="unCheckALLRecords" id="unCheckALL">Uncheck ALL</a> |
<br />
..
<table id="NoteTable"></table>
..
//..
//check ALL records
$("#checkALL").live("click", function (e)
{
e.preventDefault();
CheckALL(true);
});
//uncheck ALL records
$("#unCheckALL").live("click", function (e)
{
e.preventDefault();
CheckALL(false);
});
//..
function CheckALL(state)
{
var rows = $("#NoteTable tr");
for(var i=0; i< rows.length; i++)
{
var row = $(rows).eq(i);
var span = row.find('span#cboxSpan');
var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
if (state==true)
cb.attr('checked',true);
else
cb.attr('checked',false);
}
}
//..
上述两种技术中的任何一种都可以使用。
17) 如何显示“正在加载数据”
在加载多行数据时,应向用户显示“正在加载数据”消息。
可以根据需要的消息自定义以下 div:
..
<div id="loadMessage"></div>
..
可以使用以下 JavaScript 函数来自定义 div 区域:..
function showLoader(root, txt) {
$("#loadMessage").html("");
$("#loadMessage").show();
var loader = '<img src="' + root + '/ajax-loader.gif" align="absmiddle"> <span><br/>' + txt + '...</span>';
$("#loadMessage").fadeIn(100).html(loader);
}
function hideLoader() {
$("#loadMessage").hide();
}
..
上述两种技术中的任何一种都可以使用。
18) 如何使用 jQuery 创建主从表格(master-detail grids)?
点击主行时,详情行会显示在主表格下方,如下所示:
以下表格用作网格:
..
<table id="CountryTable" class="hovertable2"></table>
<br />
<br />
<table id="CityTable" class="hovertable"></table>
..
使用以下 JavaScript 函数模拟主从方法:..
function setTableRowClick()
{
$("#CountryTable tr td.clickable").unbind('click');
$('#CountryTable tr td.clickable').click(function ()
{
var row = $(this).parent();
setRow(row);
});
//-------------
}//func
function setRow(row)
{
var rowid = row.attr('id'); //current
var higlightedCountryTableRowid = $("#pageinfo .higlightedCountryTableRowid").text();
$("#pageinfo .higlightedCountryTableRowid").html(rowid.toString());
if ((rowid==0) || (rowid!=higlightedCountryTableRowid))
{
//------
row.siblings().removeClass('diffColor');
row.addClass("diffColor");
//-------
fillCityData(rowid);
}
}
..
function fillCountryData()
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCountryList", "Country")",
data: {},
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#CountryTable").html(data.Html);
buttonizeALL();
setLinkAbilitesCountry();
setLinkAbilitesCity();
setTableRowClick();
}
else
{
alert('opps-- country list error!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
}//func
function fillCityData(parCountryNo)
{
$.ajax({
type: "POST",
url: "@Url.Action("GetCityList", "Country")",
data: { countryNo: parCountryNo},
cache: false,
dataType: "json",
success: function (data)
{
if (data.Html)
{
$("#CityTable").html(data.Html);
buttonizeALL();
setLinkAbilitesCity();
setTableRowClick();
}
else
{
alert('opps-- city list error!');
}
},
error: function(exp)
{
alert('Error address : ' + exp.responseText);
}
}); //end ajax call
}//func
..
结论
希望本文能有所帮助。