我们继续上一节中的那个项目,给那个员工列表增加 添加修改删除功能。和上一节一样,我们先从服务器端说起,服务器端需要提供WCF接口给客户端调用,我们先来写几个BLL的数据处理方法

/**////<summary>
///获取部门列表
///</summary>
///<returns></returns>
publicstringGetDeptList()


{
varquery=fromdeptinctx.Department
selectnew


{
DeptID=dept.DepartmentID,
DeptName=dept.CnName
};
return@"{""DeptList"":"+query.ToJSON()+"}";
}

/**////<summary>
///添加员工
///</summary>
///<paramname="emp"></param>
///<returns></returns>
publicstringAddEmployee(Employeeemp)


{
try


{
ctx.Employee.InsertOnSubmit(emp);
ctx.SubmitChanges();
return"员工:"+emp.CnName+"添加成功!";
}
catch(Exceptionex)


{
return"员工:"+emp.CnName+"添加失败!"+ex.Message;
}
}
publicEmployeeGetEmployee(intempid)


{
returnctx.Employee.Single(it=>it.EmployeeID==empid);
}

/**////<summary>
///修改员工
///</summary>
///<paramname="emp"></param>
///<returns></returns>
publicstringUpdateEmployee(Employeeemp)


{
EmployeeOriginalemp=ctx.Employee.Single(it=>it.EmployeeID==emp.EmployeeID);
Originalemp.EmployeeID=emp.EmployeeID;
Originalemp.CnName=emp.CnName;
Originalemp.Sex=emp.Sex;
Originalemp.Age=emp.Age;
Originalemp.Email=emp.Email;
Originalemp.OnWorkDate=emp.OnWorkDate;
Originalemp.DepartmentID=emp.DepartmentID;
try


{
ctx.SubmitChanges();
return"员工:"+emp.CnName+"修改成功!";
}
catch(Exceptionex)


{
return"员工:"+emp.CnName+"修改失败!"+ex.Message;;
}
}

/**////<summary>
///根据员工ID数组删除员工
///</summary>
///<paramname="EmpIDArr"></param>
///<returns></returns>
publicstringDelEmployee(ArrayEmpIDArr)


{
List<Employee>emplist=newList<Employee>();
foreach(intempidinEmpIDArr)


{
Employeeemp=ctx.Employee.Single(it=>it.EmployeeID==empid);
emplist.Add(emp);
}
try


{
ctx.Employee.DeleteAllOnSubmit(emplist);
ctx.SubmitChanges();
returnEmpIDArr.Length+"个员工删除成功!";
}
catch(Exceptionex)


{
returnEmpIDArr.Length+"个员工删除失败!"+ex.Message;
}
}
然后在EmployeeService.svc文件中把这几个方法封装WCF接口

第三节#region第三节


/**////<summary>
///获取部门列表
///</summary>
///<returns></returns>
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped,RequestFormat=WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json,UriTemplate="/GetDeptList")]
publicstringGetDeptList()


{
EmployeeBLbl=newEmployeeBL();
returnbl.GetDeptList();
}

/**////<summary>
///添加员工
///</summary>
///<paramname="emp"></param>
///<returns></returns>
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped,RequestFormat=WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json,UriTemplate="/AddEmployee")]
publicstringAddEmployee(Employeeemp)


{
EmployeeBLbl=newEmployeeBL();
returnbl.AddEmployee(emp);
}

/**////<summary>
///根据员工ID获取一个员工
///</summary>
///<paramname="empID"></param>
///<returns></returns>
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped,RequestFormat=WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json,UriTemplate="/GetEmployee")]
publicEmployeeGetEmployee(intempID)


{
EmployeeBLbl=newEmployeeBL();
returnbl.GetEmployee(empID);
}

/**////<summary>
///更新员工信息
///</summary>
///<paramname="emp"></param>
///<returns></returns>
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped,RequestFormat=WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json,UriTemplate="/UpdateEmployee")]
publicstringUpdateEmployee(Employeeemp)


{
EmployeeBLbl=newEmployeeBL();
returnbl.UpdateEmployee(emp);
}

/**////<summary>
///根据员工ID数组删除员工
///</summary>
///<paramname="EmpIDArr"></param>
///<returns></returns>
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Bare,RequestFormat=WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json,UriTemplate="/DelEmployee")]
publicstringDelEmployee(ArrayEmpIDArr)


{
EmployeeBLbl=newEmployeeBL();
returnbl.DelEmployee(EmpIDArr);
}
#endregion
这样服务器端的工作就完成了,下面到客户端.也就是EXTJS的代码编写,这里要注意两个问题:
一个是关于WCF传递过来的日期型数据和从EXTJS的form中取得的日期型数据相互转化的问题,WCF传递过来的日期形式为“//Date (62831853071)//”括号里面的数字是UTC时间,我们需要设置Ext.form.DateField的format : "Y-m-d",然后把两种类型在通讯之前进行相互转化。
第二个是当BodyStyle = WebMessageBodyStyle.Wrapped 的时候WCF会自动把传递过来的值进行封装,这个在第二节的时候有详细说明,在把WCF传过来的值转化为ExtJS需要的对象的时候去掉这个封装。
基于以上两点,我写了一个WCFHelper.js的文件,代码如下:


/**//**
*[email protected]
*Date2007-12-14
*/

/**//**
*ConvertResponseText:转化从WCF获取的Object转化为ExtJS表单需要的Object
*responsetext:从WCF获取的ObjectJSON字符串
*datefieldname:JSon中的日期型字段名(属性名),多个用","分开
*wrapped:JSon字符串是否被封装(WebMessageBodyStyle.WrappedorWebMessageBodyStyle.Bare)
*ResultObject:返回值Object
*/

functionConvertResponseText(responsetext,datefieldname,wrapped,isobject)
{
varResultObject;
varobj=eval("("+responsetext+")");
if(wrapped)


{

for(varpropinobj)
{

if(typeof(prop)=='string'&&prop.substr(prop.length-6,prop.length)=='Result')
{//去掉××Result封装

if(isobject)
{
ResultObject=ConvertResponseDetail(obj[prop],datefieldname);

}else
{
ResultObject=obj[prop];
}
break;
}
}
}
else


{

if(isobject)
{
ResultObject=ConvertResponseDetail(obj,datefieldname);

}else
{
ResultObject=obj;
}
}
returnResultObject;
}

/**//***私有方法**/

functionConvertResponseDetail(obj,datefieldname)
{
varnewResult=newObject();

for(varrootPropinobj)
{

if(datefieldname.indexOf(rootProp)!=-1)
{
vardt=eval("new"+obj[rootProp].substr(1,obj[rootProp].length-2));//对UTC日期进行转化
newResult[rootProp]=DateToStr(dt);//把日期转化为字符串
}

else
{
newResult[rootProp]=obj[rootProp];
}
}
returnnewResult;
}

/**//***私有方法**/

functionDateToStr(dt)
{
varstr="";

if(dt.getFullYear)
{
vary,m,d;
y=dt.getFullYear();
m=dt.getMonth()+1;//01-12
d=dt.getDate();
m=m>9?m:"0"+m;
d=d>9?d:"0"+d;
str=y+"-"+m+"-"+d;
}
returnstr;
}

/**//**
*[email protected]
*Date2007-12-14
*/

/**//**
*ConvertFormValues:转化从表单获取的值(Object)对象为WCF需要的Object
*formvalue:从表的获取的值Object
*datefieldname:表单值的日期型字段名,多个用","分开
*ResultObject:返回值Object
*/

functionConvertFormValue(formvalue,datefieldname)
{
varResultObject=newObject();

for(varpropinformvalue)
{

if(datefieldname.indexOf(prop)!=-1)
{
vardt=StrToDate(formvalue[prop]);//字符串转化为日期
ResultObject[prop]="//Date("+Date.UTC(dt.getFullYear(),dt.getMonth(),dt.getDate())+")//";//转化为UTC日期
}

elseif(formvalue[prop]!="")
{
ResultObject[prop]=formvalue[prop];
}
}
returnResultObject;
}

/**//***私有方法**/

functionStrToDate(str)
{
vararys=newArray();
arys=str.split('-');
varnewDate=newDate(arys[0],arys[1]-1,arys[2]);
returnnewDate;
}
接下来编写paging.js代码,主要用到了Ext.FormPanel和Ext.Window 两个控件来提供编辑和添加界面,paging.js的所有代码如下,包括前一节的那部分。

/**//*

*AuthorbyXiaozhuang

*

*
*/

Ext.onReady(function()
{

//createtheDataStore

varstore=newExt.data.Store(
{
//loadusingscripttagsforcrossdomain,ifthedatainonthesamedomainas
//thispage,anHttpProxywouldbebetter

proxy:newExt.data.WCFHttpProxy(
{
url:'/EmployeeService.svc/GetEmployeePaging'
}),

//createreaderthatreadstheTopicrecords

reader:newExt.data.WCFJsonReader(
{
root:'EmployeeList',
totalProperty:'TotalCount',
id:'EmployeeID',
fields:[


{name:'EmployeeID',type:'int'},


{name:'CnName',type:'string'},


{name:'Sex',type:'string'},


{name:'Age',type:'int'},


{name:'Email',type:'string'},


{name:'OnWorkDate',type:'string'},


{name:'DeptName',type:'string'}
]
}),

//turnonremotesorting
remoteSort:true
});

store.setDefaultSort('EmployeeID','ASC');

//把true和false转化为男或者女,这个其实可以在服务器端进行转化,写在这里只是为了测试

functionrenderSex(value,p,record)
{
returnrecord.data.Sex=="true"?"男":"女";
}
//这个函数演示了怎样把服务器端的DateTime类型转为Javascript的日期

functionrenderOnWorkDate(value,p,record)
{
varjsondate=record.data.OnWorkDate;
returneval("new"+jsondate.substr(1,jsondate.length-2)).toLocaleDateString();
}

//thecolumnmodelhasinformationaboutgridcolumns
//dataIndexmapsthecolumntothespecificdatafieldin
//thedatastore
varnm=newExt.grid.RowNumberer();
varsm=newExt.grid.CheckboxSelectionModel();//addcheckboxcolumn


varcm=newExt.grid.ColumnModel([nm,sm,
{
header:"员工ID",
dataIndex:'EmployeeID',
width:100
//renderer:renderTopic

},
{
header:"姓名",
dataIndex:'CnName',
width:200

},
{
header:"性别",
dataIndex:'Sex',
width:70,
renderer:renderSex

},
{
header:"年龄",
dataIndex:'Age',
width:70


},
{
header:"Email",
dataIndex:'Email',
width:150

},
{
header:"入职时间",
dataIndex:'OnWorkDate',
width:150,
renderer:renderOnWorkDate

},
{
header:"部门",
dataIndex:'DeptName',
width:200

}]);

//bydefaultcolumnsaresortable
cm.defaultSortable=true;


vargrid=newExt.grid.GridPanel(
{
//el:'topic-grid',
renderTo:document.body,
width:800,
height:500,
title:'分页和排序列表',
store:store,
cm:cm,
trackMouseOver:false,
sm:sm,
loadMask:true,

viewConfig:
{
forceFit:true,
enableRowBody:true,
showPreview:true,

getRowClass:function(record,rowIndex,p,store)
{

return'x-grid3-row-collapsed';
}
},
//inlinetoolbars

tbar:[
{
text:'添加',
tooltip:'添加一条记录',
iconCls:'add',
handler:handleAdd

},'-',
{
text:'修改',
tooltip:'修改',
iconCls:'option',
handler:handleEdit

},'-',
{
text:'删除',
tooltip:'删除记录',
iconCls:'remove',
handler:handleDelete
}],

bbar:newExt.PagingToolbar(
{
pageSize:25,
store:store,
displayInfo:true
})
});

//renderit
grid.render();


//triggerthedatastoreload

varrequest=
{start:0,limit:25};

store.load(
{params:request});

//获取部门列表

vardeptDs=newExt.data.Store(
{

proxy:newExt.data.WCFHttpProxy(
{
url:'/EmployeeService.svc/GetDeptList'
}),

reader:newExt.data.WCFJsonReader(
{
root:'DeptList',
id:'DeptID'
},['DeptID','DeptName']
),
remoteSort:false
});


//员工信息表单

varEmpForm=newExt.FormPanel(
{
frame:true,
labelAlign:'right',
labelWidth:120,
width:450,
height:250,

items:newExt.form.FieldSet(
{
title:'员工资料',
autoHeight:true,

defaults:
{width:200},
defaultType:'textfield',

items:[newExt.form.Hidden(
{
name:'EmployeeID'

}),
{
fieldLabel:'姓名',
name:'CnName',
allowBlank:false

},newExt.form.ComboBox(
{
fieldLabel:'性别',
hiddenName:'Sex',

store:newExt.data.SimpleStore(
{
fields:['value','text'],
data:[[1,'男'],[0,'女']]
}),
valueField:'value',
displayField:'text',
typeAhead:true,
mode:'local',
triggerAction:'all',
selectOnFocus:true,
allowBlank:false

}),newExt.form.NumberField(
{
fieldLabel:'年龄',
name:'Age'

}),
{
fieldLabel:'Email',
name:'Email',
vtype:'email'

},newExt.form.DateField(
{
fieldLabel:'入职时间',
name:'OnWorkDate',
allowBlank:false,
format:"Y-m-d"

}),newExt.form.ComboBox(
{
fieldLabel:'所属部门',
name:'DepartmentName',
hiddenName:'DepartmentID',
store:deptDs,
valueField:'DeptID',
displayField:'DeptName',
typeAhead:true,
mode:'remote',
triggerAction:'all',
emptyText:'请选择部门
',
selectOnFocus:true,
allowBlank:false
})
]
})
});



functionhandleAdd()
{

varAddEmpWin=newExt.Window(
{
title:'增加新员工',
layout:'fit',
width:500,
height:300,
plain:true,
items:EmpForm,

buttons:[
{
text:'保存',
handler:AddRecord

},
{
text:'取消',

handler:function()
{
AddEmpWin.hide();
}
}]
});
AddEmpWin.show(this);
}

functionhandleEdit()
{
varselectedKeys=grid.selModel.selections.keys;//returnsarrayofselectedrowsidsonly

if(selectedKeys.length!=1)
{
Ext.MessageBox.alert('提示','请选择一条记录!');
}

else
{

varEditEmpWin=newExt.Window(
{
title:'修改员工资料',
layout:'fit',
width:500,
height:300,
plain:true,
items:EmpForm,

buttons:[
{
text:'保存',
handler:UpdateRecord

},
{
text:'取消',

handler:function()
{
EditEmpWin.hide();
}
}]
});
EditEmpWin.show(this);
//Ext.MessageBox.alert("提示",selectedKeys);
deptDs.load();//取得科室列表

varrequest=
{empID:selectedKeys[0]};

Ext.MessageBox.show(
{
msg:'正在请求数据,请稍侯',
progressText:'正在请求数据',
width:300,
wait:true,

waitConfig:
{interval:200}
});

Ext.Ajax.request(
{
url:'/EmployeeService.svc/GetEmployee',//urltoserversidescript
method:'POST',
params:Ext.util.JSON.encode(request),//theuniqueid(s)

callback:function(options,success,response)
{

if(success)
{//successwillbetrueiftherequestsucceeded
Ext.MessageBox.hide();
varformvalue=ConvertResponseText(response.responseText,"OnWorkDate",true,true);
EmpForm.form.setValues(formvalue);

}else
{
Ext.MessageBox.hide();
Ext.MessageBox.alert("失败,请重试",response.responseText);
}
},
//thefunctiontobecalleduponfailureoftherequest(serverscript,404,or403errors)

failure:function(response,options)
{
Ext.MessageBox.hide();
ReturnValue=Ext.MessageBox.alert("警告","出现异常错误!请联系管理员!");
},

success:function(response,options)
{
Ext.MessageBox.hide();
}
})//endAjaxrequest
}
}
functionUpdateRecord(btn)


{

if(EmpForm.form.isValid())
{
btn.disabled=true;

Ext.MessageBox.show(
{
msg:'正在请求数据,请稍侯',
progressText:'正在请求数据',
width:300,
wait:true,

waitConfig:
{interval:200}
});
varformvalue=EmpForm.form.getValues();

varrequest=
{emp:ConvertFormValue(formvalue,'OnWorkDate')};
//Ext.MessageBox.alert("提示",formvalues);

Ext.Ajax.request(
{
url:'/EmployeeService.svc/UpdateEmployee',//urltoserversidescript
method:'POST',
params:Ext.util.JSON.encode(request),//theuniqueid(s)

callback:function(options,success,response)
{

if(success)
{//successwillbetrueiftherequestsucceeded
Ext.MessageBox.hide();
varalertcontent=ConvertResponseText(response.responseText,"",true,false);
Ext.MessageBox.alert("成功",alertcontent);

}else
{
Ext.MessageBox.hide();
Ext.MessageBox.alert("失败,请重试",response.responseText);
}
},
//thefunctiontobecalleduponfailureoftherequest(serverscript,404,or403errors)

failure:function(response,options)
{
Ext.MessageBox.hide();
ReturnValue=Ext.MessageBox.alert("警告","出现异常错误!请联系管理员!");
},

success:function(response,options)
{
Ext.MessageBox.hide();
store.reload();
}
})//endAjaxrequest
}
}

functionAddRecord(btn)


{

if(EmpForm.form.isValid())
{
btn.disabled=true;

Ext.MessageBox.show(
{
msg:'正在请求数据,请稍侯',
progressText:'正在请求数据',
width:300,
wait:true,

waitConfig:
{interval:200}
});
varformvalue=EmpForm.form.getValues();

varrequest=
{emp:ConvertFormValue(formvalue,'OnWorkDate')};
//Ext.MessageBox.alert("提示",formvalues);

Ext.Ajax.request(
{
url:'/EmployeeService.svc/AddEmployee',//urltoserversidescript
method:'POST',
params:Ext.util.JSON.encode(request),//theuniqueid(s)

callback:function(options,success,response)
{

if(success)
{//successwillbetrueiftherequestsucceeded
Ext.MessageBox.hide();
varalertcontent=ConvertResponseText(response.responseText,"",true,false);
Ext.MessageBox.alert("成功",alertcontent);

}else
{
Ext.MessageBox.hide();
Ext.MessageBox.alert("失败,请重试",response.responseText);
}
},
//thefunctiontobecalleduponfailureoftherequest(serverscript,404,or403errors)

failure:function(response,options)
{
Ext.MessageBox.hide();
ReturnValue=Ext.MessageBox.alert("警告","出现异常错误!请联系管理员!");
},

success:function(response,options)
{
Ext.MessageBox.hide();
store.reload();
}
})//endAjaxrequest

}
}


functionhandleDelete()
{
varselectedKeys=grid.selModel.selections.keys;//returnsarrayofselectedrowsidsonly
if(selectedKeys.length>0)


{
Ext.MessageBox.confirm('提示','您确实要删除选定的记录吗?',deleteRecord);
}
else


{
Ext.MessageBox.alert('提示','请至少选择一条记录!');
}//end
}


functiondeleteRecord(btn)
{

if(btn=='yes')
{
varselectedRows=grid.selModel.selections.items;//returnsrecordobjectsforselectedrows(allinfoforrow)
varselectedKeys=grid.selModel.selections.keys;
//vardeleteresult=AjaxRequest('/EmployeeService.svc/DelEmployee',selectedKeys,false,"")

Ext.MessageBox.show(
{
msg:'正在请求数据,请稍侯',
progressText:'正在请求数据',
width:300,
wait:true,

waitConfig:
{interval:200}
});

Ext.Ajax.request(
{
url:'/EmployeeService.svc/DelEmployee',//urltoserversidescript
method:'POST',
params:Ext.util.JSON.encode(selectedKeys),//theuniqueid(s)

callback:function(options,success,response)
{

if(success)
{//successwillbetrueiftherequestsucceeded
Ext.MessageBox.hide();
varalertcontent=ConvertResponseText(response.responseText,"",false,false);
Ext.MessageBox.alert("成功",alertcontent);

}else
{
Ext.MessageBox.hide();
Ext.MessageBox.alert("失败,请重试",response.responseText);
}
},
//thefunctiontobecalleduponfailureoftherequest(serverscript,404,or403errors)

failure:function(response,options)
{
Ext.MessageBox.hide();
ReturnValue=Ext.MessageBox.alert("警告","出现异常错误!请联系管理员!");
},

success:function(response,options)
{
Ext.MessageBox.hide();
store.reload();
}
})//endAjaxrequest
}//endifclick'yes'onbutton
}//enddeleteRecord



});

运行效果:





源代码下载
数据库脚本