以前用过Ext.tree.TreePanel 做过树形结构的查询绑定,感觉TreePanel还蛮好。
今天来尝试下 结合Ext.menu.Menu 菜单做一个增删改的功能,并实现无限级的绑定,如下图的效果:
第一步:TreePanel的无限级加载设计:
我的数据设计结构如下图:
第二步:后台获取级联数据结构,返回json数据类型:
[{ " id " : 7 , " text " : " 2011 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 8 , " text " : " 春季 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 21 , " text " : " 五月 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 26 , " text " : " 第四周 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 28 , " text " : " 星期五 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 27 , " text " : " 星期四 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 23 , " text " : " 星期三 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 16 , " text " : " 星期二 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 12 , " text " : " 星期一 " , " leaf " : true , " expanded " : false , " children " :[]}]},{ " id " : 25 , " text " : " 第三周 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 24 , " text " : " 第二周 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 17 , " text " : " 第一周 " , " leaf " : true , " expanded " : false , " children " :[]}]},{ " id " : 20 , " text " : " 四月 " , " leaf " : true , " expanded " : false , " children " :[]},{ " id " : 19 , " text " : " 三月 " , " leaf " : true , " expanded " : false , " children " :[]}]}]},{ " id " : 4 , " text " : " 2010 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 13 , " text " : " 秋季 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 10 , " text " : " 九月 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 11 , " text " : " 第一周 " , " leaf " : true , " expanded " : false , " children " :[]}]}]},{ " id " : 6 , " text " : " 夏季 " , " leaf " : false , " expanded " : true , " children " :[{ " id " : 22 , " text " : " 六月 " , " leaf " : true , " expanded " : false , " children " :[]}]},{ " id " : 5 , " text " : " 春季 " , " leaf " : true , " expanded " : false , " children " :[]}]}]
实体类设计:
public partial class TSeasonProduct
{
[JsonProperty( " id " )]
public int IIdExtension
{
get
{
return this .IId;
}
}
[JsonProperty( " text " )]
public string VcNameExtension
{
get
{
return this .VcName;
}
}
[JsonProperty( " leaf " )]
public bool BIsLeafExtension
{
get
{
// return this.BIsLeaf;
return this .Children.Count == 0 ;
}
}
[JsonProperty( " expanded " )]
public bool Expanded
{
get
{
return this .BIsLeafExtension ? false : true ;
}
}
[JsonProperty( " children " )]
public List < TSeasonProduct > Children
{
get ;
set ;
}
}
我用的是Newtonsoft.Json 的序列化对象,生成json字符串。
JsonConvert.SerializeObject(obj, Formatting.None, new Newtonsoft.Json.Converters.IsoDateTimeConverter() { DateTimeFormat = " yyyy-MM-dd HH:mm:ss " });
C#的Controller的ActionResult代码:
/// <summary>
/// 产品接口
/// </summary>
/// <param name="id"> 请求参数 </param>
public ActionResult Product( string id)
{
object objJson = base .SetError( this .output);
if (base.CurrentUser != null )
{
switch (id.ToLower())
{
#region 获取产品分类列表
case " listseason " :
List < TSeasonProduct > lstSeasonProduct = this .productBusiness.GetSeason( 0 );
this .GetSeasons( ref lstSeasonProduct); // 调用递归的方法
objJson = lstSeasonProduct;
break ;
#endregion
#region 添加产品分类
case " addseason " :
try
{
string categoryName = Request[ " CategoryName " ],
pId = Request[ " ParentId " ];
int parentId = 0 ;
int .TryParse(pId, out parentId);
// 插入数据库
int seasonId = this .productBusiness.CreateSeason(categoryName, parentId);
objJson = base .SetMessage(seasonId);
}
catch (ValidationException vex)
{
objJson = base .SetError(vex.Message);
}
catch (Exception ex)
{
objJson = base .SetError(ex.Message);
}
break ;
#endregion
#region 编辑产品分类
case " editseason " :
try
{
int seasonId = 0 ;
int .TryParse(Request[ " SeasonId " ], out seasonId);
TSeasonProduct tSeason = this.productBusiness.GetSeasonByID(seasonId);
if (tSeason != null )
{
string seasonName = Request[ " SeasonName " ];
bool flag = this .productBusiness.ModifySeasonById(seasonId, seasonName);
if (flag)
{
objJson = base .SetMessage( 1 ); // 编辑成功
}
else
{
objJson = base .SetMessage( 0 ); // 编辑失败
}
}
else
{
objJson = base .SetError( " 此产品分类不存在 " );
}
}
catch (ValidationException vex)
{
objJson = base .SetError(vex.Message);
}
catch (Exception ex)
{
objJson = base .SetError(ex.Message);
}
break ;
#endregion
#region 删除产品分类
case " removeseason " :
try
{
int seasonId = 0 ;
int .TryParse(Request[ " SeasonId " ], out seasonId);
TSeasonProduct tSeason = this.productBusiness.GetSeasonByID(seasonId);
if (tSeason != null )
{
bool flag = this .productBusiness.RemoveSeasonById(seasonId);
if (flag)
{
objJson = base .SetMessage( 1 ); // 编辑成功
}
else
{
objJson = base .SetMessage( 0 ); // 编辑失败
}
}
else
{
objJson = base .SetError( " 此产品分类不存在 " );
}
}
catch (ValidationException vex)
{
objJson = base .SetError(vex.Message);
}
catch (Exception ex)
{
objJson = base .SetError(ex.Message);
}
break ;
#endregion
default :
break ;
}
}
else
{
objJson = base .SetError( " 您还没登录 " );
}
return Content( base .GenerateJson(objJson));
}
/// <summary>
/// 递归查询产品分类列表
/// </summary>
/// <param name="list"> 父级产品分类列表 </param>
private void GetSeasons( ref List < TSeasonProduct > list)
{
foreach (TSeasonProduct season in list)
{
List < TSeasonProduct > lstSeason = this .productBusiness.GetSeason(season.IId);
season.Children = lstSeason;
if (list.Count > 0 )
{
GetSeasons( ref lstSeason);
}
}
}
第三步:设计TreePanel的展示
前台Html代码:
<% @ Page Language = " C# " Inherits = " System.Web.Mvc.ViewPage " %>
<! 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 >
< title > 产品分类管理 </ title >
< link href ="/Content/resources/css/ext-all.css" rel ="stylesheet" type ="text/css" />
< link href ="/Content/manager.css" rel ="stylesheet" type ="text/css" />
< script type ="text/javascript" src ="/Scripts/ext-base.js" ></ script >
< script type ="text/javascript" src ="/Scripts/ext-all.js" ></ script >
< script type ="text/javascript" src ="/Scripts/common.js" ></ script >
< script type ="text/javascript" >
Ext.onReady( function () {
Ext.QuickTips.init();
loadTreeCategory();
});
function loadTreeCategory() {
var loader = new Ext.tree.TreeLoader({
url: " /action/product/listseason "
});
var root = new Ext.tree.AsyncTreeNode({
id: ' 0 ' ,
text: " 所有分类 " ,
leaf: false ,
loader: loader,
expandable: true ,
expanded: true
});
var treeCategory = new Ext.tree.TreePanel({
id: " treeCategories " ,
animate: true ,
enableDD: false , /* 是否支持拖拽效果 */
allowDrag: false ,
useArrows: false ,
lines: true ,
root: root,
listeners:
{
" contextMenu " : function (node, e) {
var myContextMenu = new Ext.menu.Menu({
shadow: ' frame ' ,
items: [{
iconCls: " button-add " ,
text: " 添加 " ,
scope: this ,
handler: function () {
myContextMenu.hide();
Ext.MessageBox.prompt( " 添加产品分类 " , " 名称: " , function (button, text) {
if (button == " ok " ) {
if (Ext.util.Format.trim(text) != "" ) {
addCategory(node, text);
}
}
});
}
},
{
iconCls: " button-edit " ,
text: " 编辑 " ,
handler: function () {
myContextMenu.hide();
Ext.MessageBox.prompt( " 编辑产品分类 " , " 名称: " , function (button, text) {
if (button == " ok " ) {
if (Ext.util.Format.trim(text) != "" ) {
if (node.text != text) { /* 在修改值的情况下,请求处理 */
editCategory(node, text);
}
}
}
}, this , false , node.text);
}
},
{
iconCls: " button-delete " ,
text: " 删除 " ,
handler: function () {
myContextMenu.hide();
Ext.MessageBox.confirm( " 确认删除 " , " 是否要删除指定内容? " , function (button, text) {
if (button == " yes " ) {
removeCategory(node);
}
});
}
}
]
});
if (node.parentNode == null ) { /* 主根目录没有编辑和删除的功能 */
myContextMenu.items.get( 1 ).setDisabled( true );
myContextMenu.items.get( 2 ).setDisabled( true );
} else {
if ( ! node.isLeaf()) {
myContextMenu.items.itemAt( 2 ).setDisabled( true ); /* 如果有子目录没有删除功能,根据需求而定(也可以设置删除功能) */
} else {
// myContextMenu.items.itemAt(0).setDisabled(true);
}
myContextMenu.items.itemAt( 1 ).setDisabled( false );
}
e.preventDefault();
node.select(); // 结点进入选择状态
myContextMenu.showAt(e.getPoint());
}
}
});
var panelCategory = new Ext.Panel({
title: " 产品分类管理 " ,
frame: true ,
width: 300 ,
height: 450 ,
autoScroll: true ,
iconCls: " form-window " ,
items: treeCategory,
collapsible: false
});
panelCategory.render(document.body);
}
/* 添加分类 */
function addCategory(parentNode, text) {
var parentId = parentNode.id;
Ext.Ajax.request({
url: " /action/product/addseason " , // 请求的地址
method: " POST " ,
params: { CategoryName: text, ParentId: parentId }, // 发送的参数
success: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
if (response.success > 0 ) {
createNode(parentNode, response.msg, text);
} else {
core.alert.error(response.msg);
}
},
failure: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
core.alert.error(response.msg);
}
});
}
/* 编辑分类 */
function editCategory(currentNode, text) {
Ext.Ajax.request({
url: " /action/product/editseason " , // 请求的地址
method: " POST " ,
params: { SeasonId: currentNode.id, SeasonName: text }, // 发送的参数
success: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
if (response.success == 1 ) {
if (response.msg > 0 ) {
resetNode(currentNode, text);
} else {
core.alert.error( " 修改分类失败 " );
}
} else {
core.alert.error(response.msg);
}
},
failure: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
core.alert.error(response.msg);
}
});
}
/* 删除分类 */
function removeCategory(currentNode) {
Ext.Ajax.request({
url: " /action/product/removeseason " , // 请求的地址
method: " POST " ,
params: { SeasonId: currentNode.id }, // 发送的参数
success: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
if (response.success == 1 ) {
if (response.msg > 0 ) {
removeNode(currentNode);
} else {
core.alert.error( " 删除分类失败 " );
}
} else {
core.alert.error(response.msg);
}
},
failure: function (response, option) {
response = Ext.util.JSON.decode(response.responseText);
core.alert.error(response.msg);
}
});
}
/* 创建一个TreeNode */
function createNode(node, id, text) {
var newNode = new Ext.tree.TreeNode({
id: id,
text: text,
draggable: false ,
leaf: true
});
node.appendChild(newNode);
node.leaf = false ;
// node.setIconCls('button-tree-folder-open');
node.expand();
}
/* 重置TreeNode的text */
function resetNode(node, text) {
node.setText(text);
}
/* 删除一个TreeNode */
function removeNode(node) {
var pNode = node.parentNode;
node.remove();
console.log(pNode);
var l = pNode.childNodes.length;
console.log(l);
if (l == 0 ) {
pNode.leaf = true ;
// pNode.setIconCls('button-tree-leaf');
}
}
</ script >
</ head >
< body >
</ body >
</ html >
ok,页面运行起来的效果如图:
寄语:希望喜欢asp.net mvc 和 ExtJs 的朋友多多指点! o(∩_∩)o