使用 Bootstrap 4 在 Web Forms 中实现 ASP.NET Gridview 可编辑
本文介绍使用 Bootstrap 4 实现 ASP.NET 可编辑 Gridview。
引言
我的第一篇文章是 使用 Bootstrap 4 在 Web Forms 中实现 ASP.NET Gridview。这是关于使用 Bootstrap 4 在 Web Forms 中实现 ASP.NET Gridview 可编辑的第二篇文章,它使用 Microsoft.ApplicationBlocks.Data
连接到 SQL Server。我们将构建一个新的数据库、表、存储过程和 ASP.NET 网站,并使用其他可下载的软件,通过使用 Bootstrap 编写更少的代码来实现可编辑的 gridview
。
背景
我关于使用 Bootstrap 4 在 Web Forms 中实现 ASP.NET Gridview
的第一篇文章可以在这里找到。这基于一篇文章,但本文结合了在 ASP.NET Gridview
中使用 Bootstrap 4 的可编辑功能,并提供可下载的示例。
使用代码前的软件要求
在使用代码之前,我们需要准备一个数据库、表、带 SQL Server 的存储过程,创建一个新的网站并准备其他可下载的软件。
1. 创建带文件的 ASP.NET 空网站项目
- 使用 Microsoft Visual Studio 创建一个新的名为
MyContact
的ASP.NET 空网站。 - 在 Visual Studio 中,将一个名为 bootstrap 的新文件夹添加到
MyContact
解决方案。 - 在 Visual Studio 中,将 1 个新的 Web 窗体 Default 添加到
MyContact
解决方案。 - 在 Visual Studio 中,添加新文件夹 SQL,添加一个名为 01.00.00.SqlDataProvider 的新文本文件。
- 在 Visual Studio 中,右键单击 MyContact 解决方案,添加 4 个新类:DataProvider.cs、ContactController.cs、ContactInfo.cs、Helper.cs。
- 在 Visual Studio 中,点击工具菜单,选择NuGet 程序包管理器,选择管理解决方案的 NuGet 程序包,点击浏览并搜索
Microsoft.ApplicationBlocks.Data
,然后安装它。
完成以上所有步骤后,MyContact
项目将显示如下:
2. 将 Bootstrap 文件添加到 ASP.NET 网站项目
- 从 https://bootstrap.ac.cn 下载 Bootstrap 的已编译 CSS 和 JS 文件。
- 解压缩下载的 Bootstrap 文件 bootstrap-4.0.0-dist.zip。
- 复制 css 和 js 文件夹,并将它们粘贴到
MyContact
解决方案的 bootstrap 文件夹中。
3. 使用 Bootstrap 将模板文件添加到 ASP.NET 网站项目
- 从 GitHub puikinsh/sufee-admin-dashboard 下载 Bootstrap 4 管理仪表板模板。(点击Clone or Download按钮,然后点击Download ZIP按钮)
- 解压缩下载的 sufee-admin-dashboard-master.zip 文件。
- 复制 sufee-admin-dashboard-master 文件夹中的所有文件夹和文件,并将它们粘贴到
MyContact
解决方案的 bootstrap 文件夹中。
完成以上步骤 2 和 3 后,MyContact
解决方案中的 bootstrap 文件夹将显示如下:
4. 在 SQL Server 中创建新的数据库、表和存储过程
我们将使用 Microsoft SQL Server Management Studio 运行查询来为我们的应用程序创建新的数据库、表和存储过程。包含查询的文件是 01.00.00.SqlDataProvider。
/************************************************************/
/***** SqlDataProvider *****/
/***** *****/
/***** *****/
/***** Note: To manually execute this script you must *****/
/***** perform a search and replace operation *****/
/***** *****/
/************************************************************/
SET NOCOUNT ON
GO
USE master
GO
if exists (select * from sysdatabases where name='MyContact')
drop database MyContact
go
DECLARE @device_directory NVARCHAR(520)
SELECT @device_directory = _
SUBSTRING(filename, 1, CHARINDEX(N'master.mdf', LOWER(filename)) - 1)
FROM master.dbo.sysaltfiles WHERE dbid = 1 AND fileid = 1
EXECUTE (N'CREATE DATABASE MyContact
ON PRIMARY (NAME = N''MyContact'', _
FILENAME = N''' + @device_directory + N'mycontact.mdf'')
LOG ON (NAME = N''MyContact_log'', FILENAME = N''' + _
@device_directory + N'mycontact.ldf'')')
go
set quoted_identifier on
GO
/* Set DATEFORMAT so that the date strings are interpreted correctly regardless of
the default DATEFORMAT on the server.
*/
SET DATEFORMAT mdy
GO
use "MyContact"
go
if exists (select * from sysobjects _
where id = object_id('dbo.Contacts') and sysstat & 0xf = 3)
drop table "dbo"."Contacts"
GO
CREATE TABLE "Contacts" (
"ContactId" int IDENTITY (1, 1) NOT NULL,
"FirstName" nvarchar (20) NOT NULL,
"LastName" nvarchar (20) NOT NULL,
"Address" nvarchar (60) NULL,
"City" nvarchar (15) NULL,
"Region" nvarchar (15) NULL,
"PostalCode" nvarchar (10) NULL,
"Country" nvarchar (15) NULL,
"Phone" nvarchar (24) NULL,
"EmailAddress" nvarchar (255) NULL,
"CreatedDate" datetime NOT NULL,
"UpdatedDate" datetime NULL,
CONSTRAINT "PK_Contacts" PRIMARY KEY CLUSTERED
(
"ContactId"
)
)
GO
/************************************************************/
/***** SqlDataProvider *****/
/************************************************************/
/** Drop Existing Contact Stored Procedures **/
if exists (select * from dbo.sysobjects where id = object_id(N'[GetContact]') _
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure GetContact
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[AddContact]') _
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure AddContact
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[UpdateContact]') _
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure UpdateContact
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[DeleteContact]') _
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure DeleteContact
GO
/** Create Contact Stored Procedures **/
create procedure GetContact
@ContactId int = NULL
as
DECLARE @sql nvarchar(MAX),
@paramlist nvarchar(MAX)
SELECT @sql = 'SELECT ContactId,
ContactId,
LastName,
FirstName,
Address,
City,
Region,
PostalCode,
Country,
Phone,
EmailAddress,
CreatedDate,
UpdatedDate
from Contacts with (nolock)
where 1 = 1'
IF @ContactId IS NOT NULL AND @ContactId > 0
SELECT @sql = @sql + ' AND ContactId = @xContactId'
/* IF @debug = 1 */
/* PRINT @sql */
SELECT @sql = @sql + ' order by LastName'
SELECT @paramlist = '@xContactId int'
EXEC sp_executesql @sql, @paramlist,
@ContactId
GO
create procedure AddContact
@FirstName nvarchar (20),
@LastName nvarchar (20),
@Address nvarchar (60),
@City nvarchar (15),
@Region nvarchar (15),
@PostalCode nvarchar (10),
@Country nvarchar (15),
@Phone nvarchar (24),
@EmailAddress nvarchar (255)
as
insert into Contacts (
FirstName,
LastName,
Address,
City,
Region,
PostalCode,
Country,
Phone,
EmailAddress,
CreatedDate
)
values (
@FirstName,
@LastName,
@Address,
@City,
@Region,
@PostalCode,
@Country,
@Phone,
@EmailAddress,
getdate()
)
--return the ID of the tranaction back so we can create a TransactionID
Select SCOPE_IDENTITY()
GO
create procedure UpdateContact
@ContactId int,
@FirstName nvarchar (20),
@LastName nvarchar (20),
@Address nvarchar (60),
@City nvarchar (15),
@Region nvarchar (15),
@PostalCode nvarchar (10),
@Country nvarchar (15),
@Phone nvarchar (24),
@EmailAddress nvarchar (255)
as
update Contacts
set
FirstName = @FirstName,
LastName = @LastName,
Address = @Address,
City = @City,
Region = @Region,
PostalCode = @PostalCode,
Country = @Country,
Phone = @Phone,
EmailAddress = @EmailAddress,
UpdatedDate = getdate()
where ContactId = @ContactId
GO
create procedure DeleteContact
@ContactId int
as
delete
from Contacts
where ContactId = @ContactId
GO
/************************************************************/
/***** SqlDataProvider *****/
/************************************************************/
set quoted_identifier on
go
set identity_insert "Contacts" on
go
ALTER TABLE "Contacts" NOCHECK CONSTRAINT ALL
go
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(1,'Davolio','Nancy','507 - 20th Ave. E. Apt. 2A','Seattle','WA',_
'98122','USA','(206) 555-9857','Nancy@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(2,'Fuller','Andrew','908 W. Capital Way','Tacoma','WA',_
'98401','USA','(206) 555-9482','Andrew@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(3,'Leverling','Janet','722 Moss Bay Blvd.','Kirkland','WA',_
'98033','USA','(206) 555-3412','Janet@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(4,'Peacock','Margaret','4110 Old Redmond Rd.','Redmond','WA',_
'98052','USA','(206) 555-8122','Margaret@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(5,'Buchanan','Steven','14 Garrett Hill','London',NULL,_
'SW1 8JR','UK','(71) 555-4848','Steven@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(6,'Suyama','Michael','Coventry House Miner Rd.','London',NULL,_
'EC2 7JR','UK','(71) 555-7773','Michael@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(7,'King','Robert','Edgeham Hollow Winchester Way','London',NULL,_
'RG1 9SP','UK','(71) 555-5598','Robert@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(8,'Callahan','Laura','4726 - 11th Ave. N.E.','Seattle','WA',_
'98105','USA','(206) 555-1189','Laura@mycontact.com',GETDATE())
GO
INSERT "Contacts"("ContactID","LastName","FirstName","Address","City","Region",_
"PostalCode","Country","Phone","EmailAddress","CreatedDate") _
VALUES(9,'Dodsworth','Anne','7 Houndstooth Rd.','London',NULL,_
'WG2 7LT','UK','(71) 555-4444','Anne@mycontact.com',GETDATE())
go
set identity_insert "Contacts" off
go
ALTER TABLE "Contacts" CHECK CONSTRAINT ALL
go
ContactInfo.cs 将存储联系人信息。我们有 FullName
和 FullAddress
在 Gridview
中显示。DisplayAddress
将在详细信息模态框中显示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for ContactInfo
/// </summary>
public class ContactInfo
{
//
// TODO: Add constructor logic here
//
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string EmailAddress { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public string FullAddress
{
get
{
return Address + ", " + City + ", " + Region + " " + PostalCode + " - " + Country;
}
}
public string DisplayAddress
{
get
{
return Address + "<br />" + City + ", " + Region + " " + _
PostalCode + "<br />" + Country;
}
}
}
Helper.cs 将转换对象,如下所示。我们将 DataTable
转换为对象列表,以便管理数据字段。
using Microsoft.ApplicationBlocks.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Web;
/// <summary>
/// Summary description for Helper
/// </summary>
public static class Helper
{
#region Helper
/// <summary>
/// Converts a DataTable to a list with generic objects
/// </summary>
/// <typeparam name="T">Generic object</typeparam>
/// <param name="table">DataTable</param>
/// <returns>List with generic objects</returns>
public static List<T> DataTableToList<T>(this DataTable table) where T : class, new()
{
try
{
List<T> list = new List<T>();
foreach (var row in table.AsEnumerable())
{
T obj = new T();
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
propertyInfo.SetValue(obj, Convert.ChangeType_
(row[prop.Name], propertyInfo.PropertyType), null);
}
catch
{
continue;
}
}
list.Add(obj);
}
return list;
}
catch
{
return null;
}
}
/// <summary>
/// Convert a List{T} to a DataTable.
/// </summary>
public static DataTable ListToDataTable<T>(List<T> items)
{
var tb = new DataTable(typeof(T).Name);
PropertyInfo[] props = typeof(T).GetProperties_
(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in props)
{
Type t = GetCoreType(prop.PropertyType);
tb.Columns.Add(prop.Name, t);
}
foreach (T item in items)
{
var values = new object[props.Length];
for (int i = 0; i < props.Length; i++)
{
values[i] = props[i].GetValue(item, null);
}
tb.Rows.Add(values);
}
return tb;
}
/// <summary>
/// Determine of specified type is nullable
/// </summary>
public static bool IsNullable(Type t)
{
return !t.IsValueType || _
(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
}
/// <summary>
/// Return underlying type if type is Nullable otherwise return the type
/// </summary>
public static Type GetCoreType(Type t)
{
if (t != null && IsNullable(t))
{
if (!t.IsValueType)
{
return t;
}
else
{
return Nullable.GetUnderlyingType(t);
}
}
else
{
return t;
}
}
#endregion
}
DataProvider.cs 将从 SQL Server 获取数据并将其转换为对象列表以供我们的应用程序使用。添加新记录、更新记录和删除记录将调用存储过程。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using Microsoft.ApplicationBlocks.Data;
/// <summary>
/// Summary description for DataProvider
/// </summary>
///
public abstract class DataProvider
{
public static string ConnectionString = "Data Source=localhost;
Initial Catalog=ChangeMe;User ID=sa;Password=ChangeMe";
//get { return DatabaseOwner + ObjectQualifier + ModuleQualifier; }
private static string NamePrefix
{
get { return ""; }
}
#region Request Type
public static List<ContactInfo> GetAllContacts()
{
DataSet objDS = SqlHelper.ExecuteDataset
(ConnectionString, CommandType.StoredProcedure, NamePrefix + "GetContact",
new SqlParameter("@ContactId", null));
return Helper.DataTableToList<ContactInfo>(objDS.Tables[0]);
}
public static ContactInfo GetContact(int ContactId)
{
DataSet objDS = SqlHelper.ExecuteDataset(ConnectionString,
CommandType.StoredProcedure, NamePrefix + "GetContact",
new SqlParameter("@ContactId", ContactId));
return Helper.DataTableToList<ContactInfo>(objDS.Tables[0])[0];
}
public static int AddContact(ContactInfo objInfo)
{
return Convert.ToInt32(SqlHelper.ExecuteScalar
(ConnectionString, NamePrefix + "AddContact",
new SqlParameter("@FirstName", objInfo.FirstName),
new SqlParameter("@LastName", objInfo.LastName),
new SqlParameter("@Address", objInfo.Address),
new SqlParameter("@City", objInfo.City),
new SqlParameter("@Region", objInfo.Region),
new SqlParameter("@PostalCode", objInfo.PostalCode),
new SqlParameter("@Country", objInfo.Country),
new SqlParameter("@Phone", objInfo.Phone),
new SqlParameter("@EmailAddress", objInfo.EmailAddress)
));
}
public static void UpdateContact(ContactInfo objInfo)
{
SqlHelper.ExecuteNonQuery(ConnectionString, NamePrefix + "UpdateContact",
new SqlParameter("@ContactId", objInfo.ContactId),
new SqlParameter("@FirstName", objInfo.FirstName),
new SqlParameter("@LastName", objInfo.LastName),
new SqlParameter("@Address", objInfo.Address),
new SqlParameter("@City", objInfo.City),
new SqlParameter("@Region", objInfo.Region),
new SqlParameter("@PostalCode", objInfo.PostalCode),
new SqlParameter("@Country", objInfo.Country),
new SqlParameter("@Phone", objInfo.Phone),
new SqlParameter("@EmailAddress", objInfo.EmailAddress)
);
}
public static void DeleteContact(int ContactId)
{
SqlHelper.ExecuteNonQuery(ConnectionString, NamePrefix + "DeleteContact",
new SqlParameter("@ContactId", ContactId)
);
}
#endregion
}
ContactController.cs 如下所示。 Web 应用程序将使用它来与 SQL 数据库进行接口。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Web;
/// <summary>
/// Summary description for ContactController
/// </summary>
public class ContactController
{
#region Constructors
public ContactController()
{
}
#endregion
#region Contact Public Methods
/// -----------------------------------------------------------------------------
/// <summary>
/// gets an object from the database
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="ContactId">The Id of the Contact</param>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
public List<ContactInfo> GetAllContacts()
{
return DataProvider.GetAllContacts();
}
public ContactInfo GetContact(int ContactId)
{
return DataProvider.GetContact(ContactId);
}
public int AddContact(ContactInfo objInfo)
{
return DataProvider.AddContact(objInfo);
}
public void UpdateContact(ContactInfo objInfo)
{
DataProvider.UpdateContact(objInfo);
}
public void DeleteContact(int ContactId)
{
DataProvider.DeleteContact(ContactId);
}
#endregion
}
Using the Code
Default.aspx 将使用以下代码显示可编辑的 Gridview
。gvContact_PreRender
是 Gridview
所必需的。JavaScript 在底部用于初始化 Gridview
。当 OnRowCommand
打开模态对话框时,显示会发生变化;模态框关闭后,Gridview
将刷新。
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">
<head runat="server">
<title></title>
<!-- Bootstrap -->
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<!-- Datatables-->
<link href="bootstrap/vendors/datatables.net-bs4/css/dataTables.bootstrap4.min.css"
rel="stylesheet" />
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server"></asp:ScriptManager>
<div class="container">
<div class="jumbotron text-center">
<h1>My Contact</h1>
<asp:Button ID="btnAdd"
runat="server" Text="Add New Record"
CssClass="btn btn-info" OnClick="btnAdd_Click" />
</div>
<asp:UpdatePanel ID="upCrudGrid" runat="server">
<ContentTemplate>
<asp:GridView ID="gvContact" runat="server"
AutoGenerateColumns="false" DataKeyNames="ContactId"
OnPreRender="gvContact_PreRender"
OnRowCommand="gvContact_RowCommand"
CssClass="table table-striped">
<EmptyDataTemplate>
<asp:Image ID="Image0"
ImageUrl="~/Images/yellow-warning.gif"
AlternateText="No Image" runat="server"
Visible="false" />No Data Found.
</EmptyDataTemplate>
<Columns>
<asp:ButtonField CommandName="detail"
ControlStyle-CssClass="btn btn-info"
ButtonType="Button" Text="Detail"
HeaderText="" ItemStyle-CssClass="text-center">
<ControlStyle CssClass="btn btn-info"></ControlStyle>
</asp:ButtonField>
<asp:ButtonField CommandName="editRecord"
ControlStyle-CssClass="btn btn-info"
ButtonType="Button" Text="Edit"
HeaderText="" ItemStyle-CssClass="text-center">
<ControlStyle CssClass="btn btn-info"></ControlStyle>
</asp:ButtonField>
<asp:ButtonField CommandName="deleteRecord"
ControlStyle-CssClass="btn btn-info"
ButtonType="Button" Text="Delete"
HeaderText="" ItemStyle-CssClass="text-center">
<ControlStyle CssClass="btn btn-info"></ControlStyle>
</asp:ButtonField>
<asp:BoundField DataField="FullName"
SortExpression="FullName" HeaderText="Name" />
<asp:BoundField DataField="FullAddress"
SortExpression="FullAddress" HeaderText="Address" />
<asp:BoundField DataField="Phone"
SortExpression="Phone" HeaderText="Phone" />
<asp:BoundField DataField="EmailAddress"
SortExpression="EmailAddress" HeaderText="Email Address" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
<!-- Modal -->
<div id="detailModal" class="modal hide fade"
tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 id="myModalLabel">Details</h3>
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:DetailsView ID="DetailsView1"
runat="server" CssClass="table table-bordered table-hover"
BackColor="White" ForeColor="Black"
FieldHeaderStyle-Wrap="false"
FieldHeaderStyle-Font-Bold="true"
FieldHeaderStyle-BackColor="LavenderBlush"
FieldHeaderStyle-ForeColor="Black"
BorderStyle="Groove" AutoGenerateRows="False">
<Fields>
<asp:BoundField DataField="FullName"
HeaderText="Name" />
<asp:BoundField DataField="DisplayAddress"
HeaderText="Address" HtmlEncode="false" />
<asp:BoundField DataField="Phone"
HeaderText="Phone" />
<asp:BoundField DataField="EmailAddress"
HeaderText="EmailAddress" />
<asp:BoundField DataField="CreatedDate"
HeaderText="Created Date" />
<asp:TemplateField HeaderText="Updated Date">
<ItemTemplate>
<%# (DateTime)Eval("UpdatedDate") ==
(DateTime.MinValue) ? "" : string.Format
("{0:dd/MM/yyyy hh:mm:ss tt}",
(DateTime)Eval("UpdatedDate")) %>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="gvContact"
EventName="RowCommand" />
<asp:AsyncPostBackTrigger ControlID="btnAdd"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<div class="modal-footer">
<button class="btn btn-info"
data-dismiss="modal"
aria-hidden="true">Close</button>
</div>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<!-- Modal -->
<div id="editModal" class="modal hide fade"
tabindex="-1" role="dialog"
aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 id="editModalLabel">Edit Record</h3>
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<asp:UpdatePanel ID="upEdit" runat="server">
<ContentTemplate>
<div class="modal-body">
<asp:HiddenField ID="HfUpdateID"
runat="server" />
<table class="table">
<tr>
<td>First Name : </td>
<td>
<asp:TextBox ID="txtFirstNameUpdate"
runat="server" Width="100%" />
<asp:RequiredFieldValidator
ID="valFirstNameUpdate"
ControlToValidate="txtFirstNameUpdate"
EnableClientScript="False" Display="Dynamic"
Text="<br />* First Name is required"
Font-Bold="true" ForeColor="Red"
runat="server"
ValidationGroup="ValidationGroupUpdate" />
</td>
<td>
</tr>
<tr>
<td>Last Name :</td>
<td>
<asp:TextBox ID="txtLastNameUpdate"
runat="server" Width="100%" />
<asp:RequiredFieldValidator _
ID="valLastNameUpdate"
ControlToValidate="txtLastNameUpdate"
EnableClientScript="False" Display="Dynamic"
Text="<br />* Last Name is required"
Font-Bold="true" ForeColor="Red" _
runat="server"
ValidationGroup="ValidationGroupUpdate" />
</td>
</tr>
<tr>
<td>Address :</td>
<td>
<asp:TextBox ID="txtAddressUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>City :</td>
<td>
<asp:TextBox ID="txtCityUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Region :</td>
<td>
<asp:TextBox ID="txtRegionUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Postal Code :</td>
<td>
<asp:TextBox ID="txtPostalCodeUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Country :</td>
<td>
<asp:TextBox ID="txtCountryUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Phone :</td>
<td>
<asp:TextBox ID="txtPhoneUpdate"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Email Address :</td>
<td>
<asp:TextBox ID="txtEmailAddressUpdate"
runat="server" Width="100%" /></td>
</tr>
</table>
</div>
<div class="modal-footer">
<asp:Label ID="lblResult"
Visible="false" runat="server"></asp:Label>
<asp:Button ID="btnSave"
runat="server" Text="Update"
CssClass="btn btn-info"
ValidationGroup="ValidationGroupUpdate"
OnClick="btnUpdate_Click" />
<button class="btn btn-info"
data-dismiss="modal"
aria-hidden="true">Close</button>
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="gvContact"
EventName="RowCommand" />
<asp:AsyncPostBackTrigger ControlID="btnSave"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<asp:Label ID="lblMessage" runat="server" />
<!-- Modal -->
<div id="addModal" class="modal hide fade"
tabindex="-1" role="dialog"
aria-labelledby="addModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 id="addModalLabel">Add New Record</h3>
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<asp:UpdatePanel ID="upAdd" runat="server">
<ContentTemplate>
<div class="modal-body">
<table class="table table-bordered table-hover">
<tr>
<td>First Name : </td>
<td>
<asp:TextBox ID="txtFirstNameAdd"
runat="server" Width="100%" />
<asp:RequiredFieldValidator
ID="valFirstNameAdd"
ControlToValidate="txtFirstNameAdd"
EnableClientScript="False" Display="Dynamic"
Text="<br />* First Name is required"
Font-Bold="true" ForeColor="Red"
runat="server"
ValidationGroup="ValidationGroupAdd" />
</td>
</tr>
<tr>
<td>Last Name :</td>
<td>
<asp:TextBox ID="txtLastNameAdd"
runat="server" Width="100%" />
<asp:RequiredFieldValidator ID="valLastNameAdd"
ControlToValidate="txtLastNameAdd"
EnableClientScript="False" Display="Dynamic"
Text="<br />* Last Name is required"
Font-Bold="true" ForeColor="Red"
runat="server"
ValidationGroup="ValidationGroupAdd" />
</td>
</tr>
<tr>
<td>Address :</td>
<td>
<asp:TextBox ID="txtAddressAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>City :</td>
<td>
<asp:TextBox ID="txtCityAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Region :</td>
<td>
<asp:TextBox ID="txtRegionAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Postal Code :</td>
<td>
<asp:TextBox ID="txtPostalCodeAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Country :</td>
<td>
<asp:TextBox ID="txtCountryAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Phone :</td>
<td>
<asp:TextBox ID="txtPhoneAdd"
runat="server" Width="100%" /></td>
</tr>
<tr>
<td>Email Address :</td>
<td>
<asp:TextBox ID="txtEmailAddressAdd"
runat="server" Width="100%" /></td>
</tr>
</table>
</div>
<div class="modal-footer">
<asp:Button ID="btnAddRecord" runat="server"
Text="Add" CssClass="btn btn-info"
ValidationGroup="ValidationGroupAdd"
OnClick="btnAddRecord_Click" />
<button class="btn btn-info"
data-dismiss="modal"
aria-hidden="true">Close</button>
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddRecord"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<!-- Modal -->
<div id="deleteModal" class="modal hide fade"
tabindex="-1" role="dialog"
aria-labelledby="delModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 id="delModalLabel">Delete Record</h3>
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<asp:UpdatePanel ID="upDel" runat="server">
<ContentTemplate>
<div class="modal-body">
Are you sure you want to delete the record
<asp:Label ID="lblFirstNameDelete"
runat="server"></asp:Label>
?
<asp:HiddenField ID="HfDeleteID"
runat="server" />
</div>
<div class="modal-footer">
<asp:Button ID="btnDelete"
runat="server" Text="Delete"
CssClass="btn btn-info" OnClick="btnDelete_Click" />
<button class="btn btn-info"
data-dismiss="modal"
aria-hidden="true">Cancel</button>
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnDelete"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
</div>
</form>
<!-- jQuery and Bootstrap JS files -->
<script src="bootstrap/js/jquery-3.3.1.min.js"></script>
<script src="bootstrap/js/popper.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<!-- Datatables-->
<script src="bootstrap/vendors/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="bootstrap/vendors/datatables.net-bs4/js/dataTables.bootstrap4.min.js">
</script>
<!-- pace -->
<script type="text/javascript">
$(document).ready(function () {
$('#<%= gvContact.ClientID %>').dataTable({
"aLengthMenu": [[5, 10, 50, -1], [5, 10, 50, "All"]],
"iDisplayLength": 5,
"order": [[3, "asc"]],
stateSave: true,
stateSaveCallback: function (settings, data) {
localStorage.setItem
('DataTables_' + settings.sInstance, JSON.stringify(data));
},
stateLoadCallback: function (settings) {
return JSON.parse
(localStorage.getItem('DataTables_' + settings.sInstance));
}
});
});
//The scripts below to restore the page changed by command
$('#detailModal').on('hidden.bs.modal', function () {
location.reload();
})
$('#editModal').on('hidden.bs.modal', function () {
location.reload();
})
$('#addModal').on('hidden.bs.modal', function () {
location.reload();
})
$('#deleteModal').on('hidden.bs.modal', function () {
location.reload();
})
</script>
</body>
</html>
Default.aspx.cs 如下所示。提交命令后,将显示警报对话框,Gridview
将通过 DataLoad()
刷新,Bootstrap Gridview 将通过 JavaScript location.reload().
刷新。
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
/// -----------------------------------------------------------------------------
/// <summary>
/// The initial will display the items in gridview
/// Typically your view control would be used to display content or
/// functionality in your module.
/// View may be the only control you have in your project depending on the
/// complexity of your module
/// </summary>
/// -----------------------------------------------------------------------------
public partial class _Default : System.Web.UI.Page
{
#region "Private Variables"
private ContactController objCtrl = new ContactController();
private List<ContactInfo> objInfos = new List<ContactInfo>();
private ContactInfo objInfo = new ContactInfo();
private int ContactId = 0;
#endregion
/// -----------------------------------------------------------------------------
/// <summary>
/// Page_Load runs when this program start
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void Page_Load(object sender, EventArgs e)
{
DataLoad();
}
/// -----------------------------------------------------------------------------
/// <summary>
/// DataLoad will populate the gridview
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
public void DataLoad()
{
lblMessage.Text = string.Empty;
try
{
objInfos = objCtrl.GetAllContacts();
gvContact.DataSource = objInfos;
gvContact.DataBind();
}
catch (Exception ex)
{
lblMessage.Text = ex.Message;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// gvContact_PreRender prepares gridview in bootstrap
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void gvContact_PreRender(object sender, EventArgs e)
{
GridView gv = (GridView)sender;
if ((gv.ShowHeader == true && gv.Rows.Count > 0)
|| (gv.ShowHeaderWhenEmpty == true))
{
//Force GridView to use <thead> instead of <tbody>
gv.HeaderRow.TableSection = TableRowSection.TableHeader;
}
if (gv.ShowFooter == true && gv.Rows.Count > 0)
{
//Force GridView to use <tfoot> instead of <tbody>
gv.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// gvContact_RowCommand will open specific modal dialog when the
/// button command in gridview is clicked
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void gvContact_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Find the row index
int index = Convert.ToInt32(e.CommandArgument);
// Get the ContactId and object class
int ContactId = Convert.ToInt32(gvContact.DataKeys[index].Value.ToString());
var objInfo = objInfos.Where(i => i.ContactId == ContactId).First();
if (e.CommandName.Equals("detail"))
{
var detailInfos = objInfos.Where(i => i.ContactId == ContactId);
DetailsView1.DataSource = detailInfos;
DetailsView1.DataBind();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("$('#detailModal').modal('show');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock
(this, this.GetType(), "DetailModalScript", sb.ToString(), false);
}
if (e.CommandName.Equals("editRecord"))
{
HfUpdateID.Value = objInfo.ContactId.ToString();
txtFirstNameUpdate.Text = objInfo.FirstName;
txtLastNameUpdate.Text = objInfo.LastName;
txtAddressUpdate.Text = objInfo.Address;
txtCityUpdate.Text = objInfo.City;
txtRegionUpdate.Text = objInfo.Region;
txtPostalCodeUpdate.Text = objInfo.PostalCode;
txtCountryUpdate.Text = objInfo.Country;
txtPhoneUpdate.Text = objInfo.Phone;
txtEmailAddressUpdate.Text = objInfo.EmailAddress;
lblResult.Visible = false;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("$('#editModal').modal('show');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock
(this, this.GetType(), "EditModalScript", sb.ToString(), false);
}
if (e.CommandName.Equals("deleteRecord"))
{
HfDeleteID.Value = objInfo.ContactId.ToString();
lblFirstNameDelete.Text = objInfo.FirstName;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("$('#deleteModal').modal('show');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock
(this, this.GetType(), "DeleteModalScript", sb.ToString(), false);
}
}
#region "Optional Command Interfaces"
/// -----------------------------------------------------------------------------
/// <summary>
/// btnAdd_Click will open add new record modal dialog when the
/// add new record button is clicked
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void btnAdd_Click(object sender, EventArgs e)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("$('#addModal').modal('show');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
"AddShowModalScript", sb.ToString(), false);
}
/// -----------------------------------------------------------------------------
/// <summary>
/// btnUpdate_Click will update record from modal dialog when the
/// update record button is clicked
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void btnUpdate_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
lblMessage.Text = string.Empty;
try
{
objInfo = new ContactInfo();
objInfo.ContactId = Convert.ToInt32(HfUpdateID.Value);
objInfo.FirstName = txtFirstNameUpdate.Text;
objInfo.LastName = txtLastNameUpdate.Text;
objInfo.Address = txtAddressUpdate.Text;
objInfo.City = txtCityUpdate.Text;
objInfo.Region = txtRegionUpdate.Text;
objInfo.PostalCode = txtPostalCodeUpdate.Text;
objInfo.Country = txtCountryUpdate.Text;
objInfo.Phone = txtPhoneUpdate.Text;
objInfo.EmailAddress = txtEmailAddressUpdate.Text;
objCtrl.UpdateContact(objInfo);
}
catch (Exception ex)
{
lblMessage.Text = ex.Message;
}
DataLoad();
// remove the alert() below to skip the confirm message
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("alert('Records Updated Successfully');");
sb.Append("$('#editModal').modal('hide');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock
(this, this.GetType(), "EditHideModalScript", sb.ToString(), false);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// btnDelete_Click will delete record from modal dialog
/// when the delete record button is clicked
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void btnDelete_Click(object sender, EventArgs e)
{
lblMessage.Text = string.Empty;
try
{
ContactId = Convert.ToInt32(HfDeleteID.Value);
objCtrl.DeleteContact(ContactId);
}
catch (Exception ex)
{
lblMessage.Text = ex.Message;
}
DataLoad();
// remove the alert() below to skip the confirm message
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("alert('Record deleted Successfully');");
sb.Append("$('#deleteModal').modal('hide');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
"delHideModalScript", sb.ToString(), false);
}
/// -----------------------------------------------------------------------------
/// <summary>
/// btnAddRecord_Click will add new record from modal dialog
/// when the add record button is clicked
/// </summary>
/// <remarks>
/// </remarks>
/// <history>
/// </history>
/// -----------------------------------------------------------------------------
protected void btnAddRecord_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
lblMessage.Text = string.Empty;
try
{
ContactController objCtrl = new ContactController();
ContactInfo objInfo = new ContactInfo();
objInfo.FirstName = txtFirstNameAdd.Text;
objInfo.LastName = txtLastNameAdd.Text;
objInfo.Address = txtAddressAdd.Text;
objInfo.City = txtCityAdd.Text;
objInfo.Region = txtRegionAdd.Text;
objInfo.PostalCode = txtPostalCodeAdd.Text;
objInfo.Country = txtCountryAdd.Text;
objInfo.Phone = txtPhoneAdd.Text;
objInfo.EmailAddress = txtEmailAddressAdd.Text;
objCtrl.AddContact(objInfo);
}
catch (Exception ex)
{
lblMessage.Text = ex.Message;
}
DataLoad();
// remove the alert() below to skip the confirm message
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script type='text/javascript'>");
sb.Append("alert('Record Added Successfully');");
sb.Append("$('#addModal').modal('hide');");
sb.Append(@"</script>");
ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
"AddHideModalScript", sb.ToString(), false);
}
}
#endregion
}
这是主页。
添加新记录
详细信息页面
编辑页面
删除页面
关注点
您注意到我们没有为 Gridview
创建 OnPageIndexChanging
、OnSorting
、SaveViewState
等吗?所有这些都由 Bootstrap 完成。您可以浏览子文件夹 https:///MyGridview/bootstrap/index.html 来查看 Sufee 的功能。您可以花时间学习如何为您的未来项目使用 Bootstrap 的 CSS 和 JS 文件。祝你编程愉快!
历史
这是我的第二篇文章,我希望您通过在 ASP.NET 中使用 Bootstrap 来创建 ASP.NET Gridview
时能够节省时间!