项目中用到mvc2控件扩展,任务分给了我,开发完了,结果可能要用devexpress,费了不少功夫,网上查找资料,整理成符合项目的,自己留个备份吧,一起学习

DropDownTree

第一个控件是DropDownTree,名字很形象,类似DropDownList显示形式,下拉树仿照zTree外观,比较简单,思路是后台生成HTML+jquery脚本(还有一种思路是直接通过js加载json数据不过这个不会,希望有人熟悉的给个例子)。

首先,在Scripts文件夹下新增一个js文件命名为DropDownTree.js,脚本代码如下:

DropDownTree.js 
  1 var consts = {
2 line: {
3 ROOT: "root",
4 ROOTS: "roots",
5 CENTER: "center",
6 BOTTOM: "bottom",
7 NOLINE: "noline",
8 LINE: "line"
9 },
10 folder: {
11 OPEN: "open",
12 CLOSE: "close",
13 DOCU: "docu"
14 },
15 node: {
16 CURSELECTED: "curSelectedNode",
17 A_NONE: "a_node_none"
18 }
19 }
20
21 $(function () {
22 $(".DropDownTree").dblclick(function () { //双击事件清空文本,但不清楚下拉列表选项记录
23 $(this).attr("value", "");
24 hideMenu("Div_menu_" + $(this).attr("id").split("_").pop());
25 }).click(function () { //单击显示列表哦
26 var $this = $(this);
27 var textId = $this.attr("id").split("_").pop();
28 var menuId = "Div_menu_" + $this.attr("id").split("_").pop();
29 showMenu(textId, menuId);
30 });
31
32 //a标签绑定clice 事件
33 $(".a_node_none,.curSelectedNode").bind("click", function () {
34 var aIdArr = $(this).attr("id").split("_");
35 //debugger;
36 $(".curSelectedNode").each(function () {//遍历
37 var thisId = $(this).attr("id").split("_");
38 if (thisId[2] == aIdArr[2]) {
39 $(this).removeClass(consts.node.CURSELECTED).addClass(consts.node.A_NONE).end();
40 }
41 });
42
43 $(this).addClass(consts.node.CURSELECTED).end();
44
45 if ($(this).attr("canSelect") == "true") {
46 $spNode = $(this).children(".sp_tree");
47 $("#" + $spNode.attr("id").split("_").pop()).val($spNode.html());
48 }
49 else {
50 alert("该节点不能被选择");
51 }
52 });
53
54
55 });
56
57
58
59 //textContent:TextBox's ID
60 //menuContent: 下拉div ID
61 function showMenu(textContent, menuContent) {
62
63 var treeDownObj = $("#" + textContent);
64 var treeDownOffset = $("#" + textContent).offset();
65 $("#" + menuContent).css({ left: treeDownOffset.left + "px", top: treeDownOffset.top + treeDownObj.outerHeight() + "px" }).slideDown("fast");
66
67 $("body").bind("mousedown", { id: menuContent }, onBodyDown);
68
69 //增加双击事件
70 $('.a_node_none,.curSelectedNode').dblclick(function () {
71 var menu = "Div_menu_" + textContent
72 hideMenu(menu);
73 });
74
75 }
76
77 function hideMenu(menuid) {
78 $("#" + menuid).fadeOut("fast");
79 $("body").unbind("mousedown", onBodyDown);
80 }
81
82 function onBodyDown(event) {
83 //获取事件
84 var e = event || window.event;
85 //获取元素
86 var originElement = $(e.target || e.srcElement);
87 var employeId = event.data.id.split("_"); //参数
88 var eventid = event.target.id.split("_");
89 if (!(employeId.pop() == eventid.pop())) {
90 hideMenu(event.data.id);
91 }
92 }
93
94 function bambooClick(obj) {
95 var $obj = $(obj);
96 var bamClass = $(obj).attr("class");
97 if (bamClass != "center_docu" || bamClass != "bottom_docu") {
98 var ulid = $obj.attr("id").toString().replace("bt", "ul");
99 if (bamClass.indexOf(consts.folder.OPEN) > -1) {//隐藏
100 if (bamClass.indexOf(consts.line.BOTTOM) > -1) {//last tree bamboo 区分bottom
101 $(obj).removeClass("bottom_open").addClass("bottom_close"); //bamboo
102 $(obj).next("a").children(".ico_open").removeClass("ico_open").addClass("ico_close"); //file Icon
103 $(obj).siblings("ul").hide(); //$("#" + ulid).hide(); //item
104 }
105 else { //非bottom bamboo
106 $(obj).removeClass("center_open").addClass("center_close"); //bamboo
107 $(obj).next("a").children(".ico_open").removeClass("ico_open").addClass("ico_close"); //file Icon
108 var child = $(obj).children();
109 $(obj).siblings("ul").hide();
110 }
111
112 }
113 else {//展开 center_docu
114 if (bamClass.indexOf(consts.line.BOTTOM) > -1) {//tree last bamboo
115 $(obj).removeClass("bottom_close").addClass("bottom_open"); //bamboo
116 $(obj).next("a").children(".ico_close").removeClass("ico_close").addClass("ico_open"); //file Icon
117 $(obj).siblings("ul").show();
118 //$("#" + ulid).show(); //item
119 }
120 else {
121 $(obj).removeClass("center_close").addClass("center_open"); //bamboo
122 $(obj).next("a").children(".ico_close").removeClass("ico_close").addClass("ico_open"); //file Icon
123 $(obj).siblings("ul").show(); //$("#" + ulid).show(); //item
124 }
125 }
126 }
127 }

其次,是样式文件,在Content下新增文件夹,这里命名为DownTreeStyle,在这个文件夹下新增新文件夹命名为img(放置在Tree图片,具体从网上下载,我用的3.0的),在DownTreeStyle文件夹下新增样式文件DownzTreeStyle.css,样式如下:

DownzTreeStyle.css
 1 /*-------------------------------------
2 zTree Style version: 3.0
3 修改日期:2012.1.6,殷懂礼
4 -------------------------------------*/
5
6 .ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}
7 .ztree {margin:0; padding:5px; color:#333}
8 .ztree li{padding:0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap}
9 .ztree li ul{ margin:0; padding:0 0 0 18px}
10 .ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}
11
12 .ztree li a {padding:1px 3px 0 0; margin:0 10px 0 0; cursor:pointer; height:16px; color:#333; background-color: transparent;
13 text-decoration:none; vertical-align:top; display: inline-block}
14 .ztree li a:hover {text-decoration:underline;background-color:#fbec88;}
15 .ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; border:1px #FFB951 solid;
16 opacity:0.8; filter:alpha(opacity=80)}
17 .ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black;
18 border:1px #FFB951 solid; opacity:0.8; filter:alpha(opacity=80)}
19 .ztree li a.tmpTargetNode {padding-top:0px; background-color:#316AC5; color:white; border:1px #316AC5 solid;
20 opacity:0.8; filter:alpha(opacity=80)}
21 .ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;
22 font-size:12px; border:1px #7EC4CC solid; *border:0px}
23 .ztree li span {line-height:16px; margin-right: 2px}
24 .ztree li button {width:16px; height:16px; vertical-align:middle; border:0 none; cursor: pointer;
25 background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
26 background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
27 /* 这段代码暂时没有用的上
28 .ztree li button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto}
29 .ztree li button.chk.checkbox_false_full {background-position:0 0}
30 .ztree li button.chk.checkbox_false_full_focus {background-position:0 -12px}
31 .ztree li button.chk.checkbox_true_full {background-position:0 -24px}
32 .ztree li button.chk.checkbox_true_full_focus {background-position:0 -36px}
33 .ztree li button.chk.checkbox_true_part {background-position:0 -48px}
34 .ztree li button.chk.checkbox_true_part_focus {background-position:0 -60px}
35 .ztree li button.chk.checkbox_false_part {background-position:0 -72px}
36 .ztree li button.chk.checkbox_false_part_focus {background-position:0 -84px}
37 .ztree li button.chk.radio_false_full {background-position:-13px 0}
38 .ztree li button.chk.radio_false_full_focus {background-position:-13px -12px}
39 .ztree li button.chk.radio_true_full {background-position:-13px -24px}
40 .ztree li button.chk.radio_true_full_focus {background-position:-13px -36px}
41 .ztree li button.chk.radio_true_part {background-position:-13px -48px}
42 .ztree li button.chk.radio_true_part_focus {background-position:-13px -60px}
43 .ztree li button.chk.radio_false_part {background-position:-13px -72px}
44 .ztree li button.chk.radio_false_part_focus {background-position:-13px -84px}
45 */
46 .ztree li button.switch {width:18px; height:18px}
47 .ztree li button.root_open{background-position:-62px -54px}
48 .ztree li button.root_close{background-position:-44px -54px}
49 .ztree li button.roots_open{background-position:-62px 0}
50 .ztree li button.roots_close{background-position:-44px 0}
51 .ztree li button.center_open{background-position:-62px -18px}
52 .ztree li button.center_close{background-position:-44px -18px}
53 .ztree li button.bottom_open{background-position:-62px -36px}
54 .ztree li button.bottom_close{background-position:-44px -36px}
55 .ztree li button.noline_open{background-position:-62px -72px}
56 .ztree li button.noline_close{background-position:-44px -72px}
57 .ztree li button.root_docu{ background:none;}
58 .ztree li button.roots_docu{background-position:-26px 0}
59 .ztree li button.center_docu{background-position:-26px -18px}
60 .ztree li button.bottom_docu{background-position:-26px -36px}
61 .ztree li button.noline_docu{ background:none;}
62
63 .ztree li button.ico_open{margin-right:2px; background-position:-80px -16px; vertical-align:top; *vertical-align:middle}
64 .ztree li button.ico_close{margin-right:2px; background-position:-80px 0; vertical-align:top; *vertical-align:middle}
65 .ztree li button.ico_docu{margin-right:2px; background-position:-80px -32px; vertical-align:top; *vertical-align:middle}
66 .ztree li button.edit {margin-right:2px; background-position:-80px -48px; vertical-align:top; *vertical-align:middle}
67 .ztree li button.remove {margin-right:2px; background-position:-80px -64px; vertical-align:top; *vertical-align:middle}
68
69 .ztree li button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
70
71
72 ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}
73
74 button.tmpzTreeMove_arrow {width:16px; height:16px; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;
75 background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
76 background-position:-80px -80px; background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
77
78 ul.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:auto; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}
79 .zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}
80
81
82 /*树下拉列表样式*/
83 ul.ztree {margin-top: 10px;border: 1px solid #617775;background: #ffffff;width:220px;height:360px;overflow-y:scroll;overflow-x:auto;}
84 ul.log {border: 1px solid #617775;background: #f0f6e4;width:300px;height:170px;overflow: hidden;}
85 ul.log.small {height:45px;}
86 ul.log li {color: #666666;list-style: none;padding-left: 10px;}
87 ul.log li.dark {background-color: #E3E3E3;}
88
89
90 /* level 等级样式*/
91 /*.ztree li button.level0 {
92 display:none;
93 }
94 .ztree li ul.level0 {
95 padding:0;
96 background:none;
97 }*/

然后,是mvc控件扩展,这里命名为DropDownTreeExtension.cs,代码如下:

DropDownTreeExtension.cs
  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Web.Mvc;
6 using System.Web.Routing;
7
8 namespace MVC.Extensions
9 {
10 /// <summary>
11 /// 下拉树控件
12 /// 作者:殷懂礼
13 /// 修正时间:2012-1-5
14 /// </summary>
15 public static class OmsDropDownTree
16 {
17
18 //完整控制
19 public static MvcHtmlString DropDownTree(this HtmlHelper helper, List<Node> treeSource, string id,
20 string defaultIndex, string defaultValue, float? menuWidth,
21 float? menuHeight, object htmlAttribute, bool enableEdit, bool canSelectParent
22 )
23 {
24 return MvcHtmlString.Create(GeneriteDropDownTreeStr(treeSource, id, defaultIndex, defaultValue, menuWidth, menuHeight, htmlAttribute, enableEdit, canSelectParent));
25 }
26
27 //实施默认index 和 下拉列表的高度和宽度
28 public static MvcHtmlString DropDownTree(this HtmlHelper helper, List<Node> treeSource, string id, string defaultIndex, float menuWidth, float menuHeight)
29 {
30 return MvcHtmlString.Create(GeneriteDropDownTreeStr(treeSource, id, defaultIndex, null, menuWidth, menuHeight));
31 }
32
33 //添加一个defaultIndex 设置 默认选择值的id 列表默认选择 用于编辑修改页面
34 public static MvcHtmlString DropDownTree(this HtmlHelper helper, List<Node> treeSource, string id, string defaultIndex)
35 {
36 return MvcHtmlString.Create(GeneriteDropDownTreeStr(treeSource, id, defaultIndex));
37 }
38
39 //默认参数最少 新增时候可以用这个 无默认选择值
40 public static MvcHtmlString DropDownTree(this HtmlHelper helper, List<Node> treeSource, string id)
41 {
42 return MvcHtmlString.Create(GeneriteDropDownTreeStr(treeSource, id));
43 }
44
45
46 /// <summary>
47 /// 自定义控件文本树控件
48 /// </summary>
49 /// <param name="treeSource">树数据源</param>
50 /// <param name="id">文本树页面元素id属性,注意当前页面id必须唯一,且该id不能用下划线“_”</param>
51 /// <param name="defaultIndex">默认选择树形列表的数据源索引值及节点的唯一id表示,用于编辑样式时填充数据</param>
52 /// <param name="defaultValue">文本框默认值</param>
53 /// <param name="menuWidth">设置列表宽度,默认200px</param>
54 /// <param name="menuHeight">设置列表宽度,默认自动</param>
55 /// <param name="htmlAttribute">自定义的一些控件属性</param>
56 /// <param name="readOnly">默认只读属性</param>
57 /// <param name="canSelectParent">不可选择父节点</param>
58 /// <returns></returns>
59 public static string GeneriteDropDownTreeStr(List<Node> treeSource, string id, string defaultIndex = null, string defaultValue = null,
60 float? menuWidth = 200, float? menuHeight = null, object htmlAttribute = null, bool? readOnly = false, bool? canSelectParent = false )
61 {
62 if (treeSource == null)
63 throw new ArgumentNullException("treeSource", "参数treeSource 不能为空");
64 if (id.IndexOf("_") >= 0)
65 return "<h1 style=\"color:red;\">DropDownTree控件id 不能包含下环线‘_’<h1>";
66
67 bool isHead = true;
68 string callbackValue = "";
69
70 StringBuilder responseStr = new StringBuilder();//返回整体
71 List<NodeEx> changedList = new List<NodeEx>();
72
73 string menuTreeContent = "Div_menu_" + id;
74 //responseStr.AppendFormat("<a id='menuBtn' href='#' onclick=\"showMenu('{0}','{1}')\">选择</a>", ID, menuTreeContent);//
75
76 //render List div and generate a ID for it
77
78 responseStr.AppendFormat(" <div id='{0}' class='menuContent' style='display: none; position: absolute;'> ", menuTreeContent);
79
80 if (isHead)
81 {
82 string height = "";
83 if (menuHeight != null)
84 height = "height:" + menuHeight.ToString() + "px; ";
85 responseStr.AppendFormat(" <ul id='ul_{0}' class='ztree' style='width: {1}px; {2} margin-top: 0px;'>", id, menuWidth.ToString(), height);//menuContent
86 }
87 //canSelectParent = ;
88 RenderTreeContent(treeSource, changedList, null, id, ref isHead, responseStr, defaultIndex, ref callbackValue, Convert.ToBoolean(canSelectParent));
89 responseStr.AppendFormat("</div>");
90
91 //render TextBox partial
92 var textBox = new TagBuilder("input");
93 textBox.GenerateId(id);
94 textBox.Attributes.Add("type", "text");
95
96 if (defaultValue != null && defaultIndex == null)
97 {
98 string value = defaultValue.ToString();
99 textBox.Attributes.Add("value", value);
100 }
101
102 if (!string.IsNullOrEmpty(callbackValue))
103 {
104 textBox.Attributes.Add("value", callbackValue);
105 }
106
107 if (!Convert.ToBoolean(readOnly))
108 {
109 textBox.Attributes.Add("readonly", "true");
110 }
111
112 textBox.Attributes.Add("class", "DropDownTree");//文本样式
113 textBox.MergeAttributes(new RouteValueDictionary(htmlAttribute));
114 return textBox.ToString(TagRenderMode.SelfClosing) + responseStr.ToString();
115 }
116 /// <summary>
117 /// 渲染树控件内容部分
118 /// </summary>
119 /// <param name="treeSource">树数据源</param>
120 /// <param name="processedSource">加工过的数据源</param>
121 /// <param name="parentId">父节点id</param>
122 /// <param name="controlId">树控件id</param>
123 /// <param name="isHead">是否是头节点</param>
124 /// <param name="menuTreeStr">下拉树拼接字符串</param>
125 /// <param name="selectIndex">选中的节点索引值</param>
126 /// <param name="callbackValue">选中节点的显示值</param>
127 public static void RenderTreeContent(List<Node> treeSource, List<NodeEx> processedSource, string parentId, string controlId,
128 ref bool isHead, StringBuilder menuTreeStr, string selectIndex, ref string callbackValue, bool canSelectParent)
129 {
130 List<NodeEx> layerNodes = ExNodeList(treeSource, parentId, processedSource);
131 for (int i = 0; i < layerNodes.Count(); i++)
132 {
133 string aStyle = "a_node_none";
134 if (layerNodes[i].Id == selectIndex)
135 {
136 callbackValue = layerNodes[i].Text;
137 aStyle = "curSelectedNode";
138 }
139
140 string bambooStyle = "";
141 if (isHead)
142 {
143 if (layerNodes[i].HasChild)//default open
144 bambooStyle = BambooStyle.CenterOpen;
145 else
146 bambooStyle = BambooStyle.Head;
147 }
148 else if (!layerNodes[i].HasNext)
149 {
150 if (!layerNodes[i].HasChild)
151 bambooStyle = BambooStyle.Bottom;
152 else
153 bambooStyle = BambooStyle.CenterOpen;
154 }
155 else if (layerNodes[i].HasChild)//还可以增加一个判断 树是展开还是收缩
156 bambooStyle = BambooStyle.CenterOpen;//default open
157 else
158 bambooStyle = BambooStyle.CenterDocu;
159
160 string folderFlag = "";
161 if (layerNodes[i].HasChild)
162 folderFlag = FolderStyle.FolderOpen.ToString();
163 else
164 folderFlag = FolderStyle.Fild.ToString();
165
166 if (isHead && layerNodes[i].ParentId == null)
167 {
168 isHead = false;
169 }
170
171 if (layerNodes[i].IsLead && layerNodes[i].ParentId != null)
172 {
173
174 if (!layerNodes[i].HasNext && !layerNodes[i].IsLead)
175 menuTreeStr.AppendFormat("<ul id='ul_{0}_{1}' style='display: block;'>", layerNodes[i].Id, controlId);
176 else
177 {
178 NodeEx parent = processedSource.Single(m => m.Id == layerNodes[i].ParentId);
179 if (layerNodes[i].HasNext && parent.HasNext)
180 menuTreeStr.AppendFormat("<ul class='line' id='ul_{0}_{1}' style='display: block;'>", layerNodes[i].Id, controlId);//定义 ul 的id 命名规则
181 else
182 menuTreeStr.AppendFormat("<ul id='ul_{0}_{1}' style='display: block;'>", layerNodes[i].Id, controlId);
183 }
184
185 }
186
187 if (!isHead)
188 menuTreeStr.AppendFormat("<li id='li_{0}_{1}'>", layerNodes[i].Id, controlId);//定义li的id命名规则
189
190 menuTreeStr.AppendFormat("<button title='' id='bt_{0}_{1}' class='{2}' type='button' onclick='bambooClick(this)'></button>", layerNodes[i].Id, controlId, bambooStyle);
191
192 //默认 父节点不可被选择
193 string enableSelect = Convert.ToBoolean(canSelectParent) == true ? "true" : layerNodes[i].HasChild == true ? "false" : "true";
194 menuTreeStr.AppendFormat("<a title='{0}' id='a_{1}_{2}' class='{3}' canSelect='{4}' >", layerNodes[i].Text, layerNodes[i].Id, controlId, aStyle, enableSelect);
195
196 menuTreeStr.AppendFormat("<button type='button' class='{0}' id='btf_{1}_{2}'></button>", folderFlag, layerNodes[i].Id, controlId);
197
198 menuTreeStr.AppendFormat("<span class='sp_tree' id='sp_{1}_{2}'>{3}</span>", controlId, layerNodes[i].Id, controlId, layerNodes[i].Text);
199 menuTreeStr.AppendLine("</a>");
200
201 NodeEx flag = layerNodes[i];
202
203 RenderTreeContent(treeSource, processedSource, layerNodes[i].Id, controlId, ref isHead, menuTreeStr, selectIndex, ref callbackValue, canSelectParent); //递归调用
204
205 if (layerNodes[i].ParentId == flag.ParentId)//遇到兄弟结单 结束标签
206 menuTreeStr.AppendLine("</li>");
207 if (layerNodes[i].ParentId == flag.ParentId && !layerNodes[i].HasNext)//结束ul
208 menuTreeStr.AppendLine("</ul>");
209
210 }
211
212 }
213
214 /// <summary>
215 /// 对原生树节点扩展
216 /// </summary>
217 /// <param name="treeSorce">树数据源</param>
218 /// <param name="parentId">父节点id</param>
219 /// <param name="processedSource">被扩展后的所有节点集合</param>
220 /// <returns>parentId的被扩展后的子节点集合</returns>
221 public static List<NodeEx> ExNodeList(List<Node> treeSorce, string parentId, List<NodeEx> processedSource)
222 {
223 IEnumerable<Node> head = from node in treeSorce where node.ParentId == parentId select node;
224 List<NodeEx> childList = new List<NodeEx>();
225 bool isTop = true;
226 int counter = 0;
227 foreach (Node item in head)
228 {
229 NodeEx node = new NodeEx();
230 node.Id = item.Id;
231 node.Text = item.Text;
232 node.ParentId = item.ParentId;
233
234 if (isTop)// is head only one control by ref
235 {
236 node.IsLead = true;
237 isTop = false;
238 }
239 else
240 node.IsLead = false;
241
242 if (counter == head.Count() - 1)//是否有下一个兄弟
243 node.HasNext = false;
244 else
245 node.HasNext = true;
246
247 IEnumerable<Node> hasChild = from child in treeSorce where child.ParentId == item.Id select child;
248
249 if (hasChild.Count() > 0)//是否有孩子
250 node.HasChild = true;
251 else
252 node.HasChild = false;
253 childList.Add(node);
254 processedSource.Add(node);
255 counter++;
256 }
257 return childList;
258 }
259
260 }
261
262 //树节点
263 public struct Node
264 {
265 /// <summary>
266 /// 节点id
267 /// </summary>
268 public string Id { get; set; }
269 /// <summary>
270 /// 显示值
271 /// </summary>
272 public string Text { get; set; }
273 /// <summary>
274 /// 父节点id
275 /// </summary>
276 public string ParentId { get; set; }
277 }
278
279 //内部扩展节点结构,类
280 public struct NodeEx
281 {
282 /// <summary>
283 /// id
284 /// </summary>
285 public string Id { get; set; }
286
287 /// <summary>
288 /// 显示值
289 /// </summary>
290 public string Text { get; set; }
291
292 /// <summary>
293 /// 父节点id
294 /// </summary>
295 public string ParentId { get; set; }
296
297 /// <summary>
298 /// 是否是节点开头
299 /// </summary>
300 public bool IsLead { get; set; }//竹头展开样式
301
302 /// <summary>
303 /// 是否有下个兄弟节点
304 /// </summary>
305 public bool HasNext { get; set; } //最后一个ul 中线
306 /// <summary>
307 /// 是否有孩子节点
308 /// </summary>
309 public bool HasChild { get; set; }//是否有孩子
310 }
311
312 //bambo的样式(树节点的 展开和关闭控制样式名称)
313 public static class BambooStyle
314 {
315 //根节点,没有字节点时的样式(E字头)
316 public const string Head = "roots_docu";
317 //有子节点,且节点展开
318 public const string CenterOpen = "center_open";
319 //有子节点,且节点关闭
320 public const string CenterClose = "center_close";
321 // 没有子节点
322 public const string CenterDocu = "center_docu";
323 //结尾节点
324 public const string Bottom = "bottom_docu";
325 }
326
327 //树文件夹或文件样式
328 public static class FolderStyle
329 {
330 //文件夹打开样式
331 public const string FolderOpen = "ico_open";
332 //文件夹关闭样式
333 public const string FolderClose = "ico_close";
334 //文件样式
335 public const string Fild = "ico_docu";
336 }
337 }

最后,是用法了:

  1. 在Master页,或者当前页,引入jquery最好是高版本的、DropDownTree.js、DownzTreeStyle.css;
  2. 在controller中构造 一些数据,代码如下:
    Action 方法
     
    public ActionResult TextDownTree()
    {

    List<Node> source = new List<Node>();

    for (int i = 0; i < 3; i++)
    {
    Node tree = new Node();
    tree.Id = i.ToString();
    tree.Text = "北京" + i.ToString();
    source.Add(tree);

    for (int j = 0; j < 3; j++)
    {
    Node child = new Node();
    child.ParentId = i.ToString();
    child.Id = i.ToString() + j.ToString();
    child.Text = "北京_" + i.ToString() + j.ToString();
    source.Add(child);
    for (int k = 0; k < 3; k++)
    {
    Node childs = new Node();
    childs.ParentId = child.Id;
    childs.Id = i.ToString() + j.ToString() + k.ToString();
    childs.Text = "北京_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString();
    source.Add(childs);
    }
    }
    }
    ViewData["tree"] = source;
    ViewData["index"] = "012";//默认选中的值

    string encodeTestStr = "hello viewData <br/><br/> start wrapper";
    ViewData["description"] = encodeTestStr;

    List<SelectListItem> radioList = new List<SelectListItem>();
    for (int i = 0; i < 5; i++)
    {
    SelectListItem sli = new SelectListItem();
    sli.Selected = false;
    sli.Text = "RTxt-" + i.ToString();
    sli.Value = "RVal-" + i.ToString();
    radioList.Add(sli);
    }

    ViewData["radioList"] = radioList;
    // ds.Description = ss;
    return View("treeTest");
    }
    这里不要忘记对一些类的引用一些类在DropDownTreeExtension.cs中。
  3. 在View页面用<% Html.DropDownTree(参数.....)%>就可以完成了,例如:
    View Code
    1  <%=Html.DropDownTree(ViewData["tree"] as List<Node>,"test")%>
    2 <%=Html.DropDownTree(ViewData["tree"] as List<Node>, "test1", ViewData["index"].ToString())%>
    3 <%=Html.DropDownTree(ViewData["tree"] as List<Node>, "test2")%>
    4 <%:Html.DropDownTree(ViewData["tree"] as List<Node>, "test3", ViewData["index"].ToString(), null, 300, 100, new { parenid="899-"},true,true)%>


一些效果:

日历控件

第二个是日历控件,在网上查了一个普通的日历控件,也生成了下拉的日历样子,但是一些脚本比如选择年月,需要一些时间,最后只好套用了My97 DatePicker,这样以来其实简单多了。

第一步:下载 My97 DatePicker,我用的是 My97 DatePicker 4.72 Release。在Script文件夹下新增Calendar文件夹将My97相关文件放入这个文件夹中,如:

这些文件添加完成之后,在页面只需要引用WdataPicker.js即可(view 页面或者Master页面加载),例如:   

My97 js 引用
    <!--日历控件引用开始-->
<script src="http://www.cnblogs.com/Scripts/Calendar/WdatePicker.js" type="text/javascript"></script>
<!--日历控件引用结束-->

然后mvc的控件扩展,主要用到TextBox然后加一个Class名为Wdate,代码如下:

.Wdate
{
border
: #999 1px solid; /*height: 20px;*/
background
: url("./images/datePicker.gif") no-repeat right;//My97 picture
}

 

CalendarExtension.cs
    /// <summary>
/// 日期控件
/// </summary>
public static class CalendarExtensions
{
public static MvcHtmlString Calendar(this HtmlHelper helper)
{
StringBuilder sb = new StringBuilder();
TagBuilder textCalendar = new TagBuilder("input");
textCalendar.AddCssClass("Wdate");
textCalendar.Attributes.Add("type", "text");
textCalendar.Attributes.Add("onclick", "WdatePicker()");
return MvcHtmlString.Create(textCalendar.ToString(TagRenderMode.SelfClosing));
}


public static MvcHtmlString Calendar(this HtmlHelper helper, string id)
{
StringBuilder sb = new StringBuilder();
TagBuilder txtCalendar = new TagBuilder("input");
txtCalendar.AddCssClass("Wdate");
txtCalendar.Attributes.Add("type", "text");
txtCalendar.GenerateId(id);
txtCalendar.Attributes.Add("onclick", "WdatePicker()");
return MvcHtmlString.Create(txtCalendar.ToString(TagRenderMode.SelfClosing));
}

public static MvcHtmlString Calendar(this HtmlHelper helper, string id, DateTime defaultDate)
{
StringBuilder sb = new StringBuilder();
TagBuilder txtCalendar = new TagBuilder("input");
txtCalendar.AddCssClass("Wdate");
txtCalendar.Attributes.Add("type", "text");
txtCalendar.GenerateId(id);
txtCalendar.Attributes.Add("value", string.Format("{0:d}", defaultDate).Replace('/','-'));
txtCalendar.Attributes.Add("onclick", "WdatePicker()");
return MvcHtmlString.Create(txtCalendar.ToString(TagRenderMode.SelfClosing));

}
}

这样用法就很简单了,在view页面

    <% var date = new DateTime(2011, 12, 12); %>
<%=Html.Calendar("tody",date)%>

效果:

这个My97如果想显示中文只需要在他的confg.js中配置,还有皮肤页面里面。



CheckButtonList和RadioButtonList

 这两个控件其实是一样的代码,只是,根据传入参数的类型,一个生成的Radio一个生成的是CheckBox,其实也是直接生成的html然后把这些Radio 或者 checkbox 套到td中,

具体实现的C#代码如下:

CheckListExtension.cs
    /// <summary>
/// radiobuttonList 和 checkboxList
/// author:殷懂礼
/// 修改时间:2012-1-16
/// </summary>
public static class CheckListExtensions
{
/// <summary>
/// 内用 生成radio 或者 checkbox 并 可排列
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="id">控件id</param>
/// <param name="items">列表项源</param>
/// <param name="canMultichoice">是否允许多选(false:radio;true: checkbox)</param>
/// <param name="htmlAttribute">自定义属性</param>
/// <param name="repeatColumns">排列列数</param>
/// <param name="repeatDirection">排列方向</param>
/// <returns></returns>
public static MvcHtmlString InternalCheckButtonList(this HtmlHelper htmlHelper, string id, IEnumerable<SelectListItem> items, bool canMultichoice = false, object htmlAttribute = null,
int repeatColumns = 1, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
{
string mainTagId = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(id);
if (string.IsNullOrEmpty(mainTagId))
{
throw new ArgumentException("filed can't be null or empty !", "name");
}

TagBuilder tableTag = new TagBuilder("table");
tableTag.AddCssClass("radio-main");

StringBuilder tableInnerContent = new StringBuilder();
if (repeatColumns == 1)//默认单行或列排列
{
if (repeatDirection == RepeatDirection.Horizontal)//默认 水平 单排列
{
var trTag = new TagBuilder("tr");
foreach (var item in items)
{
var tdTag = RenderRadioTd(htmlHelper, mainTagId, item, canMultichoice, htmlAttribute);
trTag.InnerHtml = tdTag.ToString();
tableInnerContent.Append(trTag.ToString());
}
}
else//垂直
{
foreach (var item in items)
{
var trTag = new TagBuilder("tr");
var tdTag = RenderRadioTd(htmlHelper, mainTagId, item, canMultichoice, htmlAttribute);
trTag.InnerHtml = tdTag.ToString();
tableInnerContent.Append(trTag.ToString());
}
}
}
else//多行或列 排列
{
int itemsCounter = items.Count();
bool isPerfectDivid = itemsCounter % repeatColumns == 0 ? true : false;
int repeatNumber = itemsCounter / repeatColumns; //重复次数
List<SelectListItem> itemList = items.ToList();

StringBuilder trContent = new StringBuilder();

TagBuilder trTag = new TagBuilder("tr");

for (int i = 0; i < itemsCounter; i++)
{
TagBuilder tdTag = RenderRadioTd(htmlHelper, mainTagId, itemList[i], canMultichoice, htmlAttribute);
trContent.Append(tdTag.ToString());
if (i != 0 && ((i + 1) % repeatColumns) == 0 && (i + 1) / repeatColumns != repeatNumber)
{
trTag.InnerHtml = trContent.ToString();
tableInnerContent.Append(trTag.ToString());
trContent.Clear();
}
else if (i == itemsCounter - 1)
{
trTag.InnerHtml = trContent.ToString();
tableInnerContent.Append(trTag.ToString());
}
}
}

tableTag.InnerHtml = tableInnerContent.ToString();
return MvcHtmlString.Create(tableTag.ToString());
}
/// <summary>
/// 生成内部 的 td 所有内容
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="mainTagName">主标签id</param>
/// <param name="item">选项</param>
/// <param name="canMultichoice">radio or checkbox</param>
/// <param name="htmlAttribute">自定义属性</param>
/// <returns></returns>
private static TagBuilder RenderRadioTd(HtmlHelper htmlHelper, string mainTagName, SelectListItem item, bool? canMultichoice = false, object htmlAttribute = null)
{
var tdTag = new TagBuilder("td");
var rbValue = item.Value ?? item.Text;
var rbName = mainTagName + "_" + rbValue;

//generate radio
var radioTag = new TagBuilder("input");
radioTag.GenerateId(rbName);
radioTag.MergeAttribute("value", rbValue);

if (item.Selected)
radioTag.MergeAttribute("checked", item.Selected.ToString());

string checkType = "";
if (Convert.ToBoolean(canMultichoice))
checkType = "checkbox";
else
checkType = "radio";

radioTag.Attributes.Add("type", checkType);
radioTag.MergeAttribute("name", mainTagName);
radioTag.MergeAttributes(new RouteValueDictionary(htmlAttribute));

var labelTag = new TagBuilder("label");
labelTag.MergeAttribute("for", rbName);
labelTag.MergeAttribute("id", rbName + "_label");
labelTag.InnerHtml = rbValue;
tdTag.InnerHtml = radioTag.ToString() + labelTag.ToString();
return tdTag;
}
}

 

富文本编辑器

 用kinderEdit 使用方法特别注意,第一需要在web.config中<system.web>   <httpRuntime requestValidationMode="2.0"/>配置这个属性,第二,在后台方法中配置[ValidateInput(false)]。第三,在.aspx 页面 配置 ValidateRequest=“false”

posted on 2012-06-25 17:28  代岳强  阅读(5465)  评论(1编辑  收藏  举报