-
引言
MVC3 提供了基于jQuery、jQuery UI的基础应用,缺少许多常用的组件,例如:页面布局、导航菜单、树形、日期时间等等。
03-树形控件
MVC3 没有提供树形控件,很多初学者到处寻找MVC3 Razor 引擎使用的树形控件,可能无奈之下选择了Telerik、Devexpress、ComponentOne等整套开发组件,又是一个从头学习的开始。
这种开发组件,有它的很优秀的特点:
1)提供基本完整的开发资源:多种皮肤、消息提示、对话框、编辑窗口、菜单、树形、网格(内置工具栏)、日期时间、选项卡、下拉框、上传文件等等,语法一致。
2)使用这样的开发组件也会形成一个群体,可以找到很多资源可供参考。
这种开发组件,弊端也是非常明显:
2)一般需要安装程序,提供相当数量的dll来支持运行环境
3)是否能够最快地产生纯净的HTML代码,DIV+CSS提供最快的运行程序?
其实,我们需要深刻理解微软为什么提供 MVC3 + EF4 这种开发框架,而又不提供大量的开发控件给程序员。其实,我们想一想:微软有着世界上最优秀的开发团队,怎么不能提供类似ASP.NET WebForm的大量控件给我们使用?当然能,而且能够做得更好!
但是,微软看到了基于 jQuery、jQuery UI开发群体的庞大和jQuery框架的优点,最终提供给我们一种更简洁的Razor引擎的语法+jQuery的开发模式,那就是MVC3。
我感觉到,微软是想让我们抛掉过去使用现成开发组件的习惯,MVC3可以把程序员引领到研发者的团队中来 !
废话啰嗦了一大堆,回过头,接着说MVC3怎么使用树形控件?
我们可以选择jQuery的控件+CSS,结合MVC3的优点,生成纯净的HTML代码,快速、高效。
介绍一个JS树形控件:jquery.dynatree.js,目前版本是1.1.1
这种树形控件功能很完善,常见的应用都提供了,而且,已经被用在MVC3开发框架上了,非常好用。
采用JSON格式的数据源,格式:
key、title、url、isFolder、isLazy、expand、select、children
1)不带选择框的数据源
[
{title: "Item 1"},
{title: "Folder 2", isFolder: true, key: "folder2",
children: [
{title: "Sub-item 2.1"},
{title: "Sub-item 2.2"}
]
},
{title: "Item 3"}
]
2)带选择框的数据源
var treeData = [
{title: "item1 with key and tooltip", tooltip: "Look, a tool tip!" },
{title: "item2: selected on init", select: true },
{title: "Folder", isFolder: true, key: "id3",
children: [
{title: "Sub-item 3.1",
children: [
{title: "Sub-item 3.1.1", key: "id3.1.1" },
{title: "Sub-item 3.1.2", key: "id3.1.2" }
]
},
{title: "Sub-item 3.2",
children: [
{title: "Sub-item 3.2.1", key: "id3.2.1" },
{title: "Sub-item 3.2.2", key: "id3.2.2" }
]
}
]
},
{title: "Document with some children (expanded on init)", key: "id4", expand: true,
children: [
{title: "Sub-item 4.1 (active on init)", activate: true,
children: [
{title: "Sub-item 4.1.1", key: "id4.1.1" },
{title: "Sub-item 4.1.2", key: "id4.1.2" }
]
},
{title: "Sub-item 4.2 (selected on init)", select: true,
children: [
{title: "Sub-item 4.2.1", key: "id4.2.1" },
{title: "Sub-item 4.2.2", key: "id4.2.2" }
]
},
{title: "Sub-item 4.3 (hideCheckbox)", hideCheckbox: true },
{title: "Sub-item 4.4 (unselectable)", unselectable: true }
]
}
];
上面这个数据源,包含了怎么禁用选择、怎么隐藏选择框、怎么初始化激活节点、展开节点、工具提示等。
3)带地址链接的数据源
[
{title: "Search engines", isFolder: true, expand: true,
children: [
{title: "Google", url: "http://www.google.com"},
{title: "Yahoo", url: "http://yahoo.com"}
]
},
{title: "jQuery", isFolder: true, expand: true,
children: [
{title: "jQuery", url: "http://www.jquery.com"},
{title: "jQuery UI", url: "http://jqueryui.com"},
{title: "API browser", url: "http://api.jquery.com"},
{title: "dynatree", url: "http://code.google.com/p/dynatree/"}
]
},
{title: "Misc", isFolder: true, expand: true,
children: [
{title: "Welcome", url: "sample-iframe-1.html"}
]
}
]
当然,单击链接,弹出窗口打开链接,如果想要在当前页面内显示,请使用iframe,或者内部链接用DIV显示网页内容
dynatree-doc.html包含常用的各种属性和事件
常用属性,举例说明
var tree = $("#tree");
tree.dynatree({
checkbox: false,// 是否显示选择框
clickFolderMode: 3,// 单击目录:1-激活, 2-展开, 3-激活并展开
selectMode: 1,// 选择模式:1-单选, 2-多选, 3:级联多选
strings: { loading: "正在加载…", loadError: "加载失败!" },// 加载提示
initAjax: { url: "/System_Area/InitTree" }, // 初始化数据请求
onPostInit: function (isReloading, isError) {// 初始化请求结束,呈现网页前
},
onLazyRead: function (node) {// 延迟加载下级节点
},
onActivate: function (node) {// 激活节点
},
onDblClick: function (node) {// 双击节点
}
});
});
当然,支持拖放调整树形,具体自己看官方提供实例。
一般我们会添加一个动态树形节点类:
public class DynamicTreeNode
{
public string key { get; set; }
public string title { get; set; }
public bool expand { get; set; }
public bool isFolder { get; set; }
public bool isLazy { get; set; }
public bool select { get; set; }
public List<DynamicTreeNode> children { get; set; }
}
List<xxx> list = (from p in db.System_Areas
select new System_Area_Tree() { AreaCode = p.AreaCode, AreaName = p.AreaName, ParentCode = p.ParentCode }).ToList();
添加一个生成树形节点的方法,业务不同,字段也不一样,自己编写这么一个类似的方法:
/// <summary>
/// 创建节点
/// </summary>
/// <param name="list">数据源</param>
/// <param name="parentNode">上级节点</param>
/// <returns></returns>
public DynamicTreeNode CreateNode(List<xxx> list, DynamicTreeNode parentNode)
{
List<xxx> rows;
string parentCode = parentNode.key;
bool root = *;//判断是否根节点
if (root)
{
rows = list.Where(*)).OrderBy(*).ToList();
}
else
{
rows = list.Where(*).OrderBy(*).ToList();
}
if (rows.Count() > 0)
{
parentNode.children = new List<DynamicTreeNode>();
}
foreach (var row in rows)
{
DynamicTreeNode itemNode = new DynamicTreeNode();
itemNode.key = row.xxxCode;
itemNode.title = row.xxxName;
List<xxx> subs = *;// 获取下级节点
if (subs.Count() == 0)
{
parentNode.children.Add(itemNode);
continue;
}
itemNode.isFolder = true;
parentNode.children.Add(CreateNode(list, itemNode));
}
return parentNode;
}
这个方法,我删除了限制层级的代码,延迟加载一般只需要加载下面一级子节点,限制层级就有必要了。
调用这个方法,返回JSON数据:
JsonResult jsonResult = new JsonResult() { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
jsonResult.Data = CreateNode(list, rootNode);
前端 initAjax: { url: "/System_Area/InitTree" } 发出的初始化请求,自动会初始化数据。
如果初始化完成,还需要加载网格数据,一般在 onPostInit 事件中处理,或者直接AJAX请求网格数据,和树形初始化并发进行效率要高一些。
如果这棵树是带选择框的,那么就需要保存数据,举例说明:
$('#save').click(function () {
// 获取选择内容
var checked = menu.dynatree("getSelectedNodes");
。。。
// 保存当前数据
$.ajax({type:'post', url: '*', data: *...});
});
讲了这么多,不知道你们听明白了没有。其实,你只要看开发包的实例,就能明白怎么使用了。动态树形1.1.1开发包见这里下载 。