ASP.NET4.0 Ajax实例--DataView模板编程2
前一篇文章中向大家介绍了如何利用客户端代码实现DataView功能,下面我们来看看如何利用DataView实现主-从模式。
想利用文字说明什么是主从模式,好像不太容易,不过通过下面的示意图说明,就比较方便,示意图如下:
上图中,左边是用户列表,右边是用户的详细信息,点击左边列表中的某一个用户名,右边就显示该用户的详细信息。这时左边就是"主",右边就是"从"。
实现主从模式(Master-Detail),可以有两种方法:
1. 绑定方式实现(自动)。
2. 代码方式实现(手动)。
一. 绑定方式的实现
利用绑定方式实现Master-Detail模式,代码量很少,开发速度快,缺点是灵活性差,因为很多情况下"从"数据是"主"数据经过运算后得到的,而不仅仅是简单的从数据库中将数据取出。因此绑定方式比较适合于直接数据显示(数据不需要经过加工就直接显示)实现过程如下:
1. 数据库设计
这里我们仍然使用Northwind数据库,我们关心的表如下图所示:
2. 和前一个Blog中的实现过程一样,我们需要添加一个WCF服务,在WCF服务中添加我们自己定义的数据访问逻辑,然后在JS里调用。和前面文章不同的是,这里我们使用EntityFramework来实现数据访问操作(在现实的工程开发中,建议大家使用EntityFramework+ADO.NET,千万不要使用LinqToSql速度太慢了)。
3. 添加EntityFramework实体类:
首先,在网站里添加新项,选择ADO.NET Entity Data Model,如下图所示:
然后,选择要映射的数据库,如下图所示:
最后,选择要映射的表,如下图所示:
生成的映射类视图,如下所示:
4. 添加一个Ajax Enabled WCF,并修改其代码,如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using NorthwindModel;
[DataContract]
public class CustomersInfo
{
[DataMember ]
public string CustomerID
{
get ;
set ;
}
[DataMember]
public string CompanyName
{
get ;
set ;
}
[DataMember]
public string ContactName
{
get ;
set ;
}
}
[DataContract]
public class OrdersInfo
{
[DataMember]
public int OrderID
{
get ;
set ;
}
[DataMember]
public DateTime OrderDate
{
get ;
set ;
}
[DataMember]
public string ShipCountry
{
get ;
set ;
}
}
[ServiceContract(Namespace = "" )]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindService
{
[OperationContract]
public List < CustomersInfo > GetAllCustomers()
{
List < CustomersInfo > result = null ;
using (NorthwindEntities context = new NorthwindEntities ())
{
result = context.Customers
.Select(customer => new CustomersInfo()
{
CustomerID = customer .CustomerID ,
CompanyName = customer.CompanyName,
ContactName = customer .ContactName
}).ToList ();
}
return result;
}
[OperationContract]
public List < OrdersInfo > GetCustomerOrders( string customerID)
{
List < OrdersInfo > result = null ;
using (NorthwindEntities context = new NorthwindEntities())
{
result = context.Orders
.Where(order => order.CustomerID == customerID)
.Select(order => new OrdersInfo()
{
OrderID = order.OrderID,
OrderDate = order.OrderDate.Value ,
ShipCountry = order .ShipCountry
}).ToList ();
}
return result;
}
}
代码说明:
1. 该WCF中包括两个方法,GetAllCustomers获取全部用户信息,GetCustomerOrders获取指定用户的订单信息。
2. 返回值中的CustomersInfo类和OrdersInfo类已经自动被标记成DataContract,所以可以直接用去WCF的数据协议。
6. 设计页面,基本布局如下图所示:
如图可见,左面是一个DataView,当选中左面某一个Customer之后,名字高亮显示,右面显示这个用户的详细信息。首先要添加一些必要的CSS,代码如下所示 :
<style type="text/css">
.sys-template
{
display : none ;
}
.left
{
float : left ;
width : 198px ;
height : 193px ;
overflow-y : scroll ;
}
.right
{
float : left ;
width : 331px ;
height : 190px ;
}
.customerRow
{
width : 100% ;
padding-top : 2px ;
border-style : solid ;
border-color : Black ;
color : Blue ;
cursor : pointer ;
}
.selectedItem
{
background-color : Gray ;
}
</style>
代码说明:
1. sys-template:所有的DataView都要应用该样式,目的是控制其可见性
2. customerRow: 显示用户名称行的样式
3. selectedItem: 当某一个用户被选中时,所选中行的样式
7. 页面的HTML代码如下:
< asp:ScriptManager ID ="ScriptManager1" runat ="server" EnableCdn ="True" >
< Services >
< asp:ServiceReference Path ="~/NorthwindService.svc" />
</ Services >
< Scripts >
< asp:ScriptReference Path = " http://ajax.microsoft.com/ajax/beta/0911/MicrosoftAjax.js "
Name = " MicrosoftAjax.js " / >
< asp:ScriptReference Path = " http://ajax.microsoft.com/ajax/beta/0911/start.debug.js " / >
</ Scripts >
</ asp:ScriptManager >
< div style ="width: 540px" >
< div id ="divLeft" class ="left" >
< div id ="dvUserList" class ="sys-template" >
< div id ="colUserName" class ="customerRow" sys:command ="Select" >
{binding CustomerID}
</ div >
</ div >
</ div >
< div id ="divRight" class ="right" >
< div id ="dvUserDetails" class ="sys-template" >
< div >
< span > CustomerID: </ span > < span > {binding CustomerID} </ span >
</ div >
< div >
< span > CompanyName: </ span > < span > {binding CompanyName} </ span >
</ div >
< div >
< span > ContactName: </ span > < span > {binding ContactName} </ span >
</ div >
</ div >
</ div >
</ div >
代码说明:
1. 和前一个Blog相同,在页面中添加了一个ScriptManager,在ScriptManager中添加了WCF的引用,以及ASP.NET Ajax Library的CDN引用,以便使用DataView控件。
2. ID为"divLeft"的DIV是左面的用户名列表区。
3. ID为"divRight"的DIV为右面的用户详细信息显示区。
4. 在"divLef"中包括一个ID为"dvUserList"的DIV,该DIV是我们使用的一个DataView,在该DataView中包括一个列,即:ID为"colCustomerID"的DIV,该列绑定到了CustomerID字段上。这里比较特殊的是,在"colCustomerID"中,我们添加了一个系统指令"sys:command="Select"",该标记的功能是:当鼠标点击这列的某一行时,该即被选定,同时该列的样式会改变成指定的样式(后面JS代码中体现),而且该DataView的selectedData属性将变成这一行所对就的记录。
5. 在"divRight"中包括一个ID为"dvUserDetails"的DIV,该DIV是用来显示用户详细信息的DataView。中间有三个列,分别绑定到CustomerID,CompanyName以及ContactName三个字段上。
8. 在页面上添加JS控制代码,如下所示:
< script >
var masterView = null ;
var detailsView = null ;
window.onload = function () {
Sys.require([Sys.components.dataView], function () {
masterView = Sys.create.dataView($get( " dvUserList " ), {
selectedItemClass: " selectedItem "
});
detailsView = Sys.create.dataView($get( " dvUserDetails " ));
Sys.bind(detailsView, " data " , masterView, " selectedData " );
NorthwindService.GetAllCustomers( function (result) {
masterView.set_data(result);
});
});
}
< / script>
代码说明:
1. masterView和detailsView分另为主从两DataView
2. 在页面加载后(window.onload),通过Sys.require来加载相关的JS文件
3. 创建masterView时,在Sys.create.dataView函数的第二个参数中,指定了masterView中的seletedItemClass属性,即:指定当masterView中的某一行被选中时所应用的样式。
4. 利用Sys.Bind函数将两个DataView进行绑定,该函数中的第一个参数用来指定将数据绑定到谁,第二个参数指定将数据绑定到该对象的哪一个属性上。第三个参数是指定要绑定的数据的来源是哪个对象,第四个参数指定数据源对象中的哪个属性是用来获取数据的。
5. 最后调用WCF Service获取所有用户数据,并利用masterView的set_data函数来绑定主DataView。
9. 运行后的效果如下图所示:
在左面用户列表中选中一个用户,右面就会显示该用户的详细信息。
二. 代码方式实现
前面是通过绑定方式实现的主—从模式。下面将功能扩展,我们还需要在点击用户的时候查看该用户的订单信息,订单信息是和Customers表关联的表,我们是无法利用简单绑定来取值的,因此,需要手动编码来控制主从模式。现在我们将页面的HTML代码做一下修改,再添加一个新的DataView,用来显示用户的订单信息。
1. 新添加的DataView的HTML代码如下所示:
2. 修改主DataView "dvUserList"的HTML如下所示:
< div id ="dvUserList" class ="sys-template" >
< div id ="colUserName" class ="customerRow"
sys:command ="Select"
sys:CustomerID ={{CustomerID}} >
{binding CustomerID}
</ div >
</ div >
代码说明:
这里为ID为"colUseName"的DIV添加了一个CustomerID属性,并将该属性绑定到CustomerID字段上。
3. 修改JS代码,如下所示:
< script >
var masterView = null ;
var detailsView = null ;
var ordersView = null ;
window.onload = function () {
Sys.require([Sys.components.dataView], function () {
masterView = Sys.create.dataView($get( " dvUserList " ), {
selectedItemClass: " selectedItem " ,
onCommand: OnUserListCommand
});
detailsView = Sys.create.dataView($get( " dvUserDetails " ));
ordersView = Sys.create.dataView($get( " dvOrdersView " ));
Sys.bind(detailsView, " data " , masterView, " selectedData " );
NorthwindService.GetAllCustomers( function (result) {
masterView.set_data(result);
});
});
}
function OnUserListCommand(sender) {
var command = sender.get_commandName();
if (command == " Select " ) {
var customerID = sender.get_commandSource().CustomerID;
NorthwindService.GetCustomerOrders(customerID, function (result) {
ordersView.set_data(result);
});
}
}
< / script>
代码说明:
1. 代码中添加了一个ordersView对象,用来表示新添加的DataView。
2. 在masterView的时候多添加了一个属性:onCommand,该属性是一个回调函数指针,该指针指向了"OnUserListCommand"函数,当鼠标对"dvUserList"中的任意一行执行操作时,OnUserListCommand函数都将被调用。
3. 在"dvUserList"中,我们只设置了select命令(sys:command="Select"),在OnUserListCommand函数中,通过调用sender.get_commandName()函数,可以知道我们对哪一个列进行了操作,因此,我们只要关心这个操作是不是"Select"即可。
4. 通过sender.get_commandSource()可以获取我们所点击的那个DIV,之前我们已经在每一行的DIV中绑定了CustomerID字段,因此,可以通过sender.get_commandSource().CustomerID来获取被点击的那一行的CustomerID值。
5. 通过调用WCF中的GetCustomerOrders函数,就可以获取指定用户的订单信息了。
4. 运行效果如下所示:
5. 完整的HTML代码如下所示:
< DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title ></ title >
< script >
var masterView = null ;
var detailsView = null ;
var ordersView = null ;
window.onload = function () {
Sys.require([Sys.components.dataView], function () {
masterView = Sys.create.dataView($get( " dvUserList " ), {
selectedItemClass: " selectedItem " ,
onCommand: OnUserListCommand
});
detailsView = Sys.create.dataView($get( " dvUserDetails " ));
ordersView = Sys.create.dataView($get( " dvOrdersView " ));
Sys.bind(detailsView, " data " , masterView, " selectedData " );
NorthwindService.GetAllCustomers( function (result) {
masterView.set_data(result);
});
});
}
function OnUserListCommand(sender, args) {
var command = sender.get_commandName();
if (command == " Select " ) {
var customerID = sender.get_commandSource().CustomerID;
NorthwindService.GetCustomerOrders(customerID, function (result) {
ordersView.set_data(result);
});
}
}
</ script >
< style type ="text/css" >
.sys-template
{
display : none ;
}
.left
{
float : left ;
width : 198px ;
height : 193px ;
overflow-y : scroll ;
}
.right
{
float : left ;
width : 331px ;
height : 190px ;
}
.customerRow
{
width : 100px ;
padding-top : 2px ;
border-style : solid ;
border-color : Black ;
border-width : 1px ;
color : Blue ;
cursor : pointer ;
}
.selectedItem
{
background-color : Gray ;
}
</ style >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:ScriptManager ID ="ScriptManager1" runat ="server" EnableCdn ="True" >
< Services >
< asp:ServiceReference Path ="~/NorthwindService.svc" />
</ Services >
< Scripts >
< asp:ScriptReference Path = " http://ajax.microsoft.com/ajax/beta/0911/MicrosoftAjax.js "
Name = " MicrosoftAjax.js " / >
< asp:ScriptReference Path = " http://ajax.microsoft.com/ajax/beta/0911/start.debug.js " / >
</ Scripts >
</ asp:ScriptManager >
< div style ="width: 540px" >
< div id ="divLeft" class ="left" >
< div id ="dvUserList" class ="sys-template" >
< div id ="colUserName" class ="customerRow"
sys:command ="Select"
sys:CustomerID ={{CustomerID}} >
{binding CustomerID} </ div >
</ div >
</ div >
< div id ="divRight" class ="right" >
< div id ="dvUserDetails" class ="sys-template" >
< div >
< span > CustomerID: </ span > < span > {binding CustomerID} </ span >
</ div >
< div >
< span > CompanyName: </ span > < span > {binding CompanyName} </ span >
</ div >
< div >
< span > ContactName: </ span > < span > {binding ContactName} </ span >
</ div >
</ div >
用户订单:
< div id ="dvOrdersView" class ="sys-template" style ="width:400px" >
< div style ="border-width:1px;border-style:solid;border-color:Black;" >
< span > {binding OrderID} </ span > -- < span > {binding OrderDate} </ span > -- < span > {binding ShipCountry} </ span >
</ div >
</ div >
</ div >
</ div >
</ div >
</ form >
</ body >
</ html >
用户订单:
< div id ="dvOrdersView" class ="sys-template" style ="width:400px" >
< div style ="border-width:1px;border-style:solid;border-color:Black;" >
< span > {binding OrderID} </ span > --
< span > {binding OrderDate} </ span > --
< span > {binding ShipCountry} </ span >
</ div >
</ div >
今天就聊到这儿,如何大家需要技术支援,请给我发Email:[email protected]