asp.net mvc + ExtJs 实现无限级TreePanel 加载、添加、编辑、删除

  以前用过Ext.tree.TreePanel 做过树形结构的查询绑定,感觉TreePanel还蛮好。

今天来尝试下 结合Ext.menu.Menu 菜单做一个增删改的功能,并实现无限级的绑定,如下图的效果:

asp.net mvc + ExtJs 实现无限级TreePanel 加载、添加、编辑、删除_第1张图片

第一步:TreePanel的无限级加载设计:

我的数据设计结构如下图:

asp.net mvc + ExtJs 实现无限级TreePanel 加载、添加、编辑、删除_第2张图片

第二步:后台获取级联数据结构,返回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 实现无限级TreePanel 加载、添加、编辑、删除_第3张图片

寄语:希望喜欢asp.net mvc 和 ExtJs 的朋友多多指点!  o(∩_∩)o 

你可能感兴趣的:(TreePanel)