一步步打造簡(jiǎn)單的MVC電商網(wǎng)站BooksStore(4)
一步步打造一個(gè)簡(jiǎn)單的 MVC 電商網(wǎng)站 - BooksStore(四)
本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore
《一步步打造一個(gè)簡(jiǎn)單的 MVC 電商網(wǎng)站 - BooksStore(一)》
《一步步打造一個(gè)簡(jiǎn)單的 MVC 電商網(wǎng)站 - BooksStore(二)》
《一步步打造一個(gè)簡(jiǎn)單的 MVC 電商網(wǎng)站 - BooksStore(三)》
《一步步打造一個(gè)簡(jiǎn)單的 MVC 電商網(wǎng)站 - BooksStore(四)》
簡(jiǎn)介
上一節(jié)我們完成了兩個(gè)主要功能:完成了整個(gè)購(gòu)物車的流程,以及訂單處理(發(fā)郵件進(jìn)行通知),今天我們來(lái)學(xué)習(xí)一下最基本的增刪改查,以及登錄認(rèn)證過(guò)濾器,加入防 CSRF 攻擊,本系列已完結(jié)。
該系列主要功能與知識(shí)點(diǎn)如下:
分類、產(chǎn)品瀏覽、購(gòu)物車、結(jié)算、CRUD(增刪改查) 管理、發(fā)郵件、分頁(yè)、模型綁定、認(rèn)證過(guò)濾器和單元測(cè)試等。
【備注】項(xiàng)目使用 VS2015 + C#6 進(jìn)行開發(fā),有問(wèn)題請(qǐng)發(fā)表在留言區(qū)哦,還有,頁(yè)面長(zhǎng)得比較丑,請(qǐng)見諒。
目錄
基本的增刪改查 CRUD
登錄授權(quán)認(rèn)證過(guò)濾
基本的增刪改查 CRUD
我們創(chuàng)建一個(gè)新的控制器進(jìn)行增刪改查功能,AdminController,并添加一個(gè)顯示所有數(shù)據(jù)的方法:

/// <summary>
/// 后臺(tái)管理控制器
/// </summary>
public class AdminController : Controller
{
private readonly IBookRepository _bookRepository;
public AdminController(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
/// <summary>
/// 首頁(yè)
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
return View(_bookRepository.Books);
}
}
不在沿用之前的布局頁(yè)了,創(chuàng)建一個(gè)新的布局頁(yè) _AdmindLayout.cshtml:

<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <link href="~/Contents/admin/Site.css" rel="stylesheet" /> </head> <body> <div> @RenderBody() </div> </body> </html>
Site.css
.table {
width: 100%;
padding: 0;
margin: 0;
}
.table th {
font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
color: #4f6b72;
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
border-top: 1px solid #C1DAD7;
letter-spacing: 2px;
text-transform: uppercase;
text-align: left;
padding: 6px 6px 6px 12px;
background: #CAE8EA no-repeat;
}
.table td {
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
background: #fff;
font-size: 14px;
padding: 6px 6px 6px 12px;
color: #4f6b72;
}
.table td.alt {
background: #F5FAFA;
color: #797268;
}
.table th.spec, td.spec {
border-left: 1px solid #C1DAD7;
}
對(duì)應(yīng)的Index.cshtml:
@model IEnumerable<Wen.BooksStore.Domain.Entities.Book>
@{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<p>
@Html.ActionLink("新增", "Edit")
</p>
<table class="table">
<tr>
<th>
名稱
</th>
<th>
描述
</th>
<th>
價(jià)格
</th>
<th>
分類
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category)
</td>
<td>
@Html.ActionLink("編輯", "Edit", new { id = item.Id })
@using (Html.BeginForm("Delete", "Admin", FormMethod.Post, new { style = "display:inline;" }))
{
@Html.Hidden("id", item.Id)
<input type="submit" value="刪除" />
}
</td>
</tr>
}
</table>

編輯,我把新增和編輯的位置放在一塊,使用 id 進(jìn)行區(qū)分,如果 id = 0 就表示新增的信息。
在 AdminCtroller 中添加關(guān)于編輯的方法
/// <summary>
/// 編輯
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ActionResult Edit(int id = 0)
{
if (id == 0)
{
return View(new Book());
}
var model = _bookRepository.Books.FirstOrDefault(x => x.Id == id);
return View(model);
}
/// <summary>
/// 編輯
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
[HttpPost]
public ActionResult Edit(Book book)
{
if (!ModelState.IsValid)
{
return View(book);
}
_bookRepository.SaveBook(book);
return RedirectToAction("Index");
}
更新存儲(chǔ)庫(kù)中的方法:

IBookRepository.cs
/// <summary>
/// 書存儲(chǔ)庫(kù)接口
/// </summary>
public interface IBookRepository
{
/// <summary>
/// 書模型集合
/// </summary>
IQueryable<Book> Books { get; }
/// <summary>
/// 保存書
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
int SaveBook(Book book);
/// <summary>
/// 刪除書
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Book DeleteBook(int id);
}
EfBookRepository.cs
/// <summary>
/// 書存儲(chǔ)庫(kù)
/// </summary>
public class EfBookRepository : IBookRepository
{
private readonly EfDbContext _context = new EfDbContext();
/// <summary>
/// 書模型集合
/// </summary>
public IQueryable<Book> Books => _context.Books;
/// <summary>
/// 保存書
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
public int SaveBook(Book book)
{
if (book.Id == 0)
{
_context.Books.Add(book);
}
else
{
var model = _context.Books.Find(book.Id);
if (model==null)
{
return 0;
}
model.Category = book.Category;
model.Description = book.Description;
model.Name = book.Name;
model.Price = book.Price;
}
return _context.SaveChanges();
}
/// <summary>
/// 刪除書
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Book DeleteBook(int id)
{
var model = _context.Books.Find(id);
if (model == null)
{
return null;
}
_context.Books.Remove(model);
_context.SaveChanges();
return model;
}
}
需要對(duì) Book 模型加上驗(yàn)證用的特性:
[Table("Book")]
public class Book
{
/// <summary>
/// 標(biāo)識(shí)
/// </summary>
public int Id { get; set; }
/// <summary>
/// 名稱
/// </summary>
[Required(ErrorMessage = "名稱不能為空")]
public string Name { get; set; }
/// <summary>
/// 描述
/// </summary>
[Required(ErrorMessage = "描述不能為空")]
public string Description { get; set; }
/// <summary>
/// 價(jià)格
/// </summary>
[Required(ErrorMessage = "價(jià)格不能為空")]
[Range(0.01, double.MaxValue, ErrorMessage = "請(qǐng)?zhí)顚懞线m的價(jià)格")]
public decimal Price { get; set; }
/// <summary>
/// 分類
/// </summary>
[Required(ErrorMessage = "分類不能為空")]
public string Category { get; set; }
}
_AdminLayout.cshtml 需要引入驗(yàn)證用的 js(客戶端驗(yàn)證):
<script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery.validate.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
Edit.cshtml
@model Wen.BooksStore.Domain.Entities.Book
@{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h2>編輯</h2>
<div>
@Html.ValidationSummary()
<div>
@using (Html.BeginForm())
{
@Html.HiddenFor(x => x.Id)
<table>
<tr>
<td>名稱</td>
<td>@Html.TextBoxFor(x => x.Name)</td>
</tr>
<tr>
<td>價(jià)格</td>
<td>@Html.TextBoxFor(x => x.Price)</td>
</tr>
<tr>
<td>分類</td>
<td>@Html.TextBoxFor(x => x.Category)</td>
</tr>
<tr>
<td>描述</td>
<td>@Html.TextAreaFor(x => x.Description)</td>
</tr>
</table>
<input type="submit" value="提交" />
}
</div>
</div>

圖:錯(cuò)誤提示

刪除
/// <summary>
/// 刪除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost]
public ActionResult Delete(int id)
{
_bookRepository.DeleteBook(id);
return RedirectToAction("Index");
}
加入提示,我們?cè)谛略?、編輯和刪除時(shí)應(yīng)該加入必要的提示信息,使用TempData。

/Admin/Index.cshtml 下的也要添加:

執(zhí)行效果:

【備注】TempData 臨時(shí)數(shù)據(jù)保存了一條信息,是一個(gè)“鍵/值”字典,類似會(huì)話 Session 和 ViewBag,它和 Session 的差別是,在 HTTP 請(qǐng)求結(jié)束后會(huì)被刪除。因?yàn)檫@里使用了 RedirectToAction ,一條重定向指令,會(huì)告訴瀏覽器重定向請(qǐng)求到一個(gè)新地址,這時(shí)就不能使用 ViewBag,ViewBag 用于在控制器與視圖之間傳遞數(shù)據(jù),但它保持?jǐn)?shù)據(jù)的時(shí)間不能比當(dāng)前的HTTP 請(qǐng)求長(zhǎng),重定向意味著用戶是跨請(qǐng)求的,ViewBag 不能用于跨請(qǐng)求時(shí)傳遞數(shù)據(jù)。
登錄授權(quán)認(rèn)證過(guò)濾
上面是一個(gè) Admin 的后臺(tái)管理操作,不是每一個(gè)用戶都能夠進(jìn)入管理的,所以現(xiàn)在加入登錄授權(quán)認(rèn)證功能,只有成功后,才能進(jìn)入管理界面。
先在配置文件 WebConfig.cs 中加入
<authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout="2880"> <credentials passwordFormat="Clear"> <user name="admin" password="123"/> </credentials> </forms> </authentication>
WebConfig.cs
<?xml version="1.0" encoding="utf-8"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=301880 --> <configuration> <connectionStrings> <add name="EfDbContext" connectionString="server=.;database=TestDb;uid=sa;pwd=123" providerName="System.Data.SqlClient"/> </connectionStrings> <appSettings> <add key="webpages:Version" value="3.0.0.0"/> <add key="webpages:Enabled" value="false"/> <add key="ClientValidationEnabled" value="true"/> <add key="UnobtrusiveJavaScriptEnabled" value="true"/> <add key="SendEmailName" value="943239005@qq.com"/> </appSettings> <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout="2880"> <credentials passwordFormat="Clear"> <user name="admin" password="123"/> </credentials> </forms> </authentication> <compilation debug="true" targetFramework="4.6.1"/> <httpRuntime targetFramework="4.6.1"/> <httpModules> <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/> </httpModules> </system.web> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/> <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/> </dependentAssembly> </assemblyBinding> </runtime> <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/> <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+"/> </compilers> </system.codedom> <system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules> <remove name="ApplicationInsightsWebTracking"/> <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler"/> </modules> </system.webServer> </configuration>
在這里使用的授權(quán)認(rèn)證模式為表單認(rèn)證,為了簡(jiǎn)化與數(shù)據(jù)庫(kù)的交互操作,采取的是硬編碼的形式。如果尚未得到認(rèn)證,會(huì)跳轉(zhuǎn)到 Account/Login 的地址讓管理員先進(jìn)行登錄,timeout 表示登錄(即認(rèn)證)成功的保持時(shí)長(zhǎng)為 2880 分鐘(即 48 小時(shí)),而 name 表示的就是用戶名, password 表示的就是登錄密碼?! ?/p>
這里采用的是授權(quán)認(rèn)證過(guò)濾器,我們需要對(duì)要認(rèn)證后才能進(jìn)入的控制器添加一個(gè)特性[Authorize],即對(duì) AdminController 添加該特性。

新建表單認(rèn)證提供器,一個(gè)接口和一個(gè)實(shí)現(xiàn):

IAuthProvider.cs:
public interface IAuthProvider
{
/// <summary>
/// 認(rèn)證
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <returns></returns>
bool Auth(string userName, string password);
}
FormsAuthProvider.cs:
/// <summary>
/// 表單認(rèn)證提供者
/// </summary>
public class FormsAuthProvider:IAuthProvider
{
/// <summary>
/// 認(rèn)證
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool Auth(string userName, string password)
{
var result = FormsAuthentication.Authenticate(userName, password);
if (result)
{
//設(shè)置認(rèn)證 Cookie
FormsAuthentication.SetAuthCookie(userName, false);
}
return result;
}
}
AddBindings() 方法中注冊(cè):
/// <summary>
/// 添加綁定
/// </summary>
private void AddBindings()
{
_kernel.Bind<IBookRepository>().To<EfBookRepository>();
_kernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>();
_kernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
}

/// <summary>
/// 登錄視圖模型
/// </summary>
public class LoginViewModel
{
[Required(ErrorMessage = "用戶名不能為空")]
public string UserName { get; set; }
[Required(ErrorMessage = "密碼不能為空")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
新建 AccountController

public class AccountController : Controller
{
private readonly IAuthProvider _authProvider;
public AccountController(IAuthProvider authProvider)
{
_authProvider = authProvider;
}
/// <summary>
/// 登錄
/// </summary>
/// <returns></returns>
public ActionResult Login()
{
return View();
}
/// <summary>
/// 登錄
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(new LoginViewModel());
}
var result = _authProvider.Auth(model.UserName, model.Password);
if (result) return RedirectToAction("Index", "Admin");
ModelState.AddModelError("", "賬號(hào)或用戶名有誤");
return View(new LoginViewModel());
}
}
Login.cshtml 登錄頁(yè)面:
@model Wen.BooksStore.WebUI.Models.LoginViewModel
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登錄</title>
@*<link rel="stylesheet" >*@
<link rel="stylesheet" >
@*<link href="~/Contents/Login/css/htmleaf-demo.css" rel="stylesheet" />*@
<style type="text/css">
@@import url(https://fonts.googleapis.com/css?family=Roboto:300);
.login-page {
margin: auto;
padding: 8% 0 0;
width: 360px;
}
.form {
background: #FFFFFF;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
margin: 0 auto 100px;
max-width: 360px;
padding: 45px;
position: relative;
text-align: center;
z-index: 1;
}
.form input {
background: #f2f2f2;
border: 0;
box-sizing: border-box;
font-family: "Roboto", sans-serif;
font-size: 14px;
margin: 0 0 15px;
outline: 0;
padding: 15px;
width: 100%;
}
.form button {
-webkit-transition: all 0.3 ease;
background: #4CAF50;
border: 0;
color: #FFFFFF;
cursor: pointer;
font-family: "Microsoft YaHei", "Roboto", sans-serif;
font-size: 14px;
outline: 0;
padding: 15px;
text-transform: uppercase;
transition: all 0.3 ease;
width: 100%;
}
.form button:hover, .form button:active, .form button:focus { background: #43A047; }
.form .message {
color: #b3b3b3;
font-size: 12px;
margin: 15px 0 0;
}
.form .message a {
color: #4CAF50;
text-decoration: none;
}
.form .register-form { display: none; }
.container {
margin: 0 auto;
max-width: 300px;
position: relative;
z-index: 1;
}
.container:before, .container:after {
clear: both;
content: "";
display: block;
}
.container .info {
margin: 50px auto;
text-align: center;
}
.container .info h1 {
color: #1a1a1a;
font-size: 36px;
font-weight: 300;
margin: 0 0 15px;
padding: 0;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
.container .info span .fa { color: #EF3B3A; }
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background: #76b852; /* fallback for old browsers */
background: -webkit-linear-gradient(right, #76b852, #8DC26F);
background: -moz-linear-gradient(right, #76b852, #8DC26F);
background: -o-linear-gradient(right, #76b852, #8DC26F);
background: linear-gradient(to left, #76b852, #8DC26F);
font-family: "Roboto", sans-serif;
}
</style>
<!--[if IE]>
<script src="http://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
<div id="wrapper" class="login-page">
<div id="login_form" class="form">
@using (Html.BeginForm("Login", "Account", FormMethod.Post, new { @class = "login-form" }))
{
<span style="float: left; color: red;">@Html.ValidationSummary()</span>
@Html.AntiForgeryToken()
@Html.TextBoxFor(x => x.UserName, new { placeholder = "用戶名" })
@Html.EditorFor(x => x.Password, new { placeholder = "密碼", })
<input type="submit" value="登 錄" />
}
</div>
</div>
</body>
</html>


【備注】ValidateAntiForgeryToken 特性用于防止跨站請(qǐng)求偽造(CSRF)攻擊。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 一步步打造簡(jiǎn)單的MVC電商網(wǎng)站BooksStore(3)
- 一步步打造簡(jiǎn)單的MVC電商網(wǎng)站BooksStore(1)
- MVC4制作網(wǎng)站教程第四章 更新欄目4.3
- MVC4制作網(wǎng)站教程第四章 添加欄目4.1
- asp.net mvc驗(yàn)證碼類使用
- MVC使用極驗(yàn)驗(yàn)證制作登錄驗(yàn)證碼學(xué)習(xí)筆記7
- ASP.NET MVC驗(yàn)證碼功能實(shí)現(xiàn)代碼
- ASP.NET?MVC5網(wǎng)站開發(fā)之添加、刪除、重置密碼、修改密碼、列表瀏覽管理員篇2(六)
- ASP.NET MVC5網(wǎng)站開發(fā)之登錄、驗(yàn)證和注銷管理員篇1(六)
- MVC+EasyUI+三層新聞網(wǎng)站建立 建站準(zhǔn)備工作(一)
相關(guān)文章
.Net Core 實(shí)現(xiàn)圖片驗(yàn)證碼的實(shí)現(xiàn)示例
這篇文章主要介紹了.Net Core 實(shí)現(xiàn)圖片驗(yàn)證碼的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
.net mvc頁(yè)面UI之Jquery博客日歷控件實(shí)現(xiàn)代碼
最近在做一個(gè)博客系統(tǒng),其他需要用到博客日歷控件,網(wǎng)上搜索了很多資料,其中大部分都是javascript的,經(jīng)過(guò)總結(jié)使用jquery實(shí)現(xiàn)了博客日歷效果。代碼如下2013-09-09
ASP.NET MVC中SignalR的簡(jiǎn)單應(yīng)用
這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC中SignalR的簡(jiǎn)單應(yīng)用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
解決ASP.NET Core Mvc文件上傳限制問(wèn)題實(shí)例
本篇文章主要介紹了解決ASP.NET Core Mvc文件上傳限制問(wèn)題,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11
ASP.NET2.0緩存(Cache)技術(shù)深入理解
緩存技術(shù)是ASP.NET2.0非常重要的一個(gè)特性,它提供了一種非常好的本地?cái)?shù)據(jù)緩存機(jī)制,從而有效的提高數(shù)據(jù)訪問(wèn)的性能2012-11-11
asp.net中Word轉(zhuǎn)Html的辦法(不需要WORD組件)
最近碰到一個(gè)需求,在文本編輯器中實(shí)現(xiàn)“Word導(dǎo)入”功能 發(fā)現(xiàn)了幾種方法,只是作為總結(jié)使用2013-04-04
Gridview使用CheckBox全選與單選采用js實(shí)現(xiàn)同時(shí)高亮顯示選擇行
Gridview使用CheckBox單選與全選功能再次進(jìn)行簡(jiǎn)單演示,選中的行,使用高亮顯示,讓用戶一目了然看到哪一行被選擇了,在項(xiàng)目中很實(shí)用的,開發(fā)中的朋友們可要考慮一下哦2013-01-01

