您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程
Discuz的NT控件剖析Tab属性页
宛儿2025-07-08Discuz教程已有人查阅
导读继上篇文章之后(链接),大家给了一些反馈和意见,有些我已动手进行了部分修改,将会在2.0版本中提供给大家。希望大家能继续支持我们这个开源项目。
继上篇文章之后(链接),大家给了一些反馈和意见,有些我已动手进行了部分修改,将会在2.0版本中提供给大家。希望大家能继续支持我们这个开源项目。
好了,开始今天的话题,今天就说一下Tab控件。
先贴一张运行效果图让大家看一下:
开发动机:在去年开发后台功能时,最早使用的是ComponentArt控件库。相信园子里有不少人都用过这个商业控件库。在beta1版正式发布后,才有时间将这个库中的控件一个一个的替除出来,其中就有tabs 控件。因为必定是商业控件,所以还是自己设计开发的用着踏实。
今天这个下载包中的控件代码可是全新,这些代码如果不出意外的话,将会随同2.0版本一起发布出去。同时为了使用方便,我将一些样式部分的代码单拿出来(因为2.0版本中样式表采用继承的方式进行设计)。现在就按下载包中的文件逐一给大家做一下说明:
在Discuz.Controls项目中的admin/tab/目录下有下面一些文件
TabControl.cs : tab控件的主体类,主要负责前端UI代码的生成,事件订制,子控件生成等
TabControlDesigner.cs :顾名思义,这里对TabControl控件进行设计时支持的类
TabEditorForm.cs : 对tab控件中的属性页进行添加,修改,删除进行可视化支持的窗体类
TabEditor.cs : 对在TabEditorForm窗体中操作的数据保存到设计时页面进行支持
TabPage.cs : 属性页控件类,作为TabControl的子控件进行显示其中的内容并进行相关属性绑定
TabPageCollection.cs : 将TabPage类实例以数据 形式提供给TabControl的ITEM属性
现在大家就应该对整个控件有一个大概了解了吧!
那么现在就对这几个文件中的关键代码作一下概述:
TabControl.cs 中的服务器端事件处理,定义及其postback过程处理如下
TabControlDesigner.cs 文件的源码如下(请看一下注释即可):
相关主要代码如下:
里面的代码很好理解,这里就不多说什么了。
其余的TabPage.cs,和TabPageCollection.cs文件都是相对简单的设计,其中主要看一下TabPage类中的Render函数即可下面再将相关的JS贴上,以便大家进行对照:
好了,开始今天的话题,今天就说一下Tab控件。
先贴一张运行效果图让大家看一下:
开发动机:在去年开发后台功能时,最早使用的是ComponentArt控件库。相信园子里有不少人都用过这个商业控件库。在beta1版正式发布后,才有时间将这个库中的控件一个一个的替除出来,其中就有tabs 控件。因为必定是商业控件,所以还是自己设计开发的用着踏实。
今天这个下载包中的控件代码可是全新,这些代码如果不出意外的话,将会随同2.0版本一起发布出去。同时为了使用方便,我将一些样式部分的代码单拿出来(因为2.0版本中样式表采用继承的方式进行设计)。现在就按下载包中的文件逐一给大家做一下说明:
在Discuz.Controls项目中的admin/tab/目录下有下面一些文件
TabControl.cs : tab控件的主体类,主要负责前端UI代码的生成,事件订制,子控件生成等
TabControlDesigner.cs :顾名思义,这里对TabControl控件进行设计时支持的类
TabEditorForm.cs : 对tab控件中的属性页进行添加,修改,删除进行可视化支持的窗体类
TabEditor.cs : 对在TabEditorForm窗体中操作的数据保存到设计时页面进行支持
TabPage.cs : 属性页控件类,作为TabControl的子控件进行显示其中的内容并进行相关属性绑定
TabPageCollection.cs : 将TabPage类实例以数据 形式提供给TabControl的ITEM属性
现在大家就应该对整个控件有一个大概了解了吧!
那么现在就对这几个文件中的关键代码作一下概述:
TabControl.cs 中的服务器端事件处理,定义及其postback过程处理如下
1 private static readonly object TabSelectedIndexChangedEvent;
2
3 public event EventHandler TabSelectedIndexChanged
4 {
5 add
6 {
7 base.Events.AddHandler(TabControl.TabSelectedIndexChangedEvent, value);
8 }
9 remove
10 {
11 base.Events.RemoveHandler(TabControl.TabSelectedIndexChangedEvent, value);
12 }
13 }
14
15 protected void OnTabSelectedIndexChanged(EventArgs e)
16 {
17 if (base.Events != null)
18 {
19 EventHandler handler1 = (EventHandler)base.Events[TabSelectedIndexChangedEvent];
20 if (handler1 != null)
21 {
22 handler1(this, e);
23 }
24 }
25 }
26
27 void IPostBackDataHandler.RaisePostDataChangedEvent()
28 {
29 this.OnTabSelectedIndexChanged(EventArgs.Empty);
30 }
31
32
其余主要属性参见注释代码:
1 //当选定某一属性页索引值时
2 public int SelectedIndex
3 {
4 get
5 {
6 if (this.Items.Count <= 0)
7 {
8 return (this._SelectedIndex = -1);
9 }
10 if (this._SelectedIndex == -1)
11 {
12 for (int i = 0; i < this.Items.Count; i++)
13 {
14
15
16 return this._SelectedIndex;
17 }
18 set
19 {
20 if ((value < -1) || (value >= this.Items.Count))
21 {
22 throw new ArgumentOutOfRangeException("选项页必须小于" + this.Items.Count.ToString());
23 }
24 this._SelectedIndex = value;
25 }
26 }
27
28
29 [Description("顶部属性页标题距左边偏移量"), DefaultValue(0)]
30 public int LeftOffSetX
31 {
32 get
33 {
34 object obj = ViewState["LeftOffSetX"];
35 return obj == null ? 0 : Convert.ToInt32(obj.ToString());
36 }
37 set
38 {
39 ViewState["LeftOffSetX"] = value;
40 }
41 }
42
这个控件的render函数实现逻辑很清楚,这里就不多说了,大家可以去看一下相关代码就行了。TabControlDesigner.cs 文件的源码如下(请看一下注释即可):
1 public class TabControlDesigner : ControlDesigner
2 {
3 protected override string GetEmptyDesignTimeHtml()
4 {
5 return CreatePlaceHolderDesignTimeHtml("右击选择创建新的属性页");
6 }
7
8 private DesignerVerbCollection _verbs;
9
10 //定义处理的动作
11 public override DesignerVerbCollection Verbs
12 {
13 get
14 {
15 if (_verbs == null)
16 {
17 _verbs = new DesignerVerbCollection(new DesignerVerb[] { new DesignerVerb("创建新的属性页", new EventHandler(this.OnBuildTabStrip)) });
18 }
19
20 return _verbs;
21 }
22 }
23
24
25 //处理动作要运行的操作,这里是显示TabEditorForm窗体
26 private void OnBuildTabStrip(object sender, EventArgs e)
27 {
28 TabEditor oEditor = new TabEditor();
29 oEditor.EditComponent(this.Component);
30 }
31
32 //得到设计时Html代码
33 public override string GetDesignTimeHtml()
34 {
35
36 try
37 {
38 TabControl oTabStrip = ((TabControl)Component);
39
40 if (oTabStrip.Items == null || oTabStrip.Items.Count == 0)
41 {
42 return GetEmptyDesignTimeHtml();
43 }
44
45 System.Text.StringBuilder oSB = new System.Text.StringBuilder();
46 StringWriter oStringWriter = new StringWriter(oSB);
47 HtmlTextWriter oWriter = new HtmlTextWriter(oStringWriter);
48
49 oTabStrip.RenderDownLevelContent(oWriter);
50 oWriter.Flush();
51 oStringWriter.Flush();
52
53 return oSB.ToString();
54 }
55 catch (Exception ex)
56 {
57 return CreatePlaceHolderDesignTimeHtml("生成设计时代码错误:\n\n" + ex.ToString());
58 }
59 }
60 }
TabEditor.cs文件的内容主要是用于对操作数据绑定到相关的web设计页面。相关主要代码如下:
1 internal class TabEditor : WindowsFormsComponentEditor
2 {
3 public override bool EditComponent(ITypeDescriptorContext context, object component, IWin32Window owner)
4 {
5 TabControl oControl = (TabControl)component;
6 IServiceProvider site = oControl.Site;
7 IComponentChangeService changeService = null;
8
9 DesignerTransaction transaction = null;
10 bool changed = false;
11
12 try
13 {
14 if (site != null)
15 {
16 IDesignerHost designerHost = (IDesignerHost)site.GetService(typeof(IDesignerHost));
17 transaction = designerHost.CreateTransaction("BuildTabStrip");
18
19 changeService = (IComponentChangeService)site.GetService(typeof(IComponentChangeService));
20 if (changeService != null)
21 {
22 try
23 {
24 changeService.OnComponentChanging(component, null);
25 }
26 catch (CheckoutException ex)
27 {
28 if (ex == CheckoutException.Canceled)
29 return false;
30 throw ex;
31 }
32 }
33 }
34
35 try
36 {
37 TabEditorForm oEditorForm = new TabEditorForm(oControl);
38 if (oEditorForm.ShowDialog(owner) == DialogResult.OK)
39 {
40 changed = true;
41 }
42 }
43 finally
44 {
45 if (changed && changeService != null)
46 {
47 changeService.OnComponentChanged(oControl, null, null, null);
48 }
49 }
50 }
51 finally
52 {
53 if (transaction != null)
54 {
55 if (changed)
56 {
57 transaction.Commit();
58 }
59 else
60 {
61 transaction.Cancel();
62 }
63 }
64 }
65
66 return changed;
67 }
68 }
这块功能的注释因为开发时间问题,以后会加进去,但这些代码因为存在很大的通用性,所以大家可以用在自己的控件设计中:)TabEditorForm.cs 这个窗体运行时的效果如下:里面的代码很好理解,这里就不多说什么了。
其余的TabPage.cs,和TabPageCollection.cs文件都是相对简单的设计,其中主要看一下TabPage类中的Render函数即可下面再将相关的JS贴上,以便大家进行对照:
1 function tabpage_mouseover(e)
2 {
3 if(e.className == "CurrentTabSelect")
4 {
5 return ;
6 }
7
8 if(e.className != "OnTabSelect")
9 {
10 e.className = "OnTabSelect";
11 }
12 }
13
14 function tabpage_mouseout(e)
15 {
16 if(e.className == "CurrentTabSelect")
17 {
18 return ;
19 }
20 if(e.className != "TabSelect")
21 {
22 e.className = "TabSelect";
23 }
24 }
25
26 function tabpage_selectonserver(e,tabpageid)
27 {
28 e.parentNode.parentNode.childNodes[0].value = tabpageid;
29 }
30
31 function tabpage_selectonclient(e,tabpageid)
32 {
33 tabdiv = e.parentNode;
34
35 var tabpagediv = getElementsByClassName('tab-page','div',document);
36 var tabareas = getElementsByClassName('tabarea','div',document);
37
38 for(i=0;i<tabdiv.childNodes.length;i++)
39 {
40 tabdiv.childNodes.className = "TabSelect";
41 tabdiv.childNodes.childNodes[0].className = "";
42 }
43
44 for(i=0;i<tabpagediv.length;i++)
45 {
46 if(tabpagediv.id.indexOf(e.id.split(':')[0])>=0)
47 {
48 tabpagediv.style.display = "none";
49 }
50 }
51
52 //对当前结点的子结点(所有)设置属性
53 for(i=0;i<tabareas.length;i++)
54 {
55 if(tabareas.id.indexOf(e.id.replace('_li',''))>=0)
56 {
57 tabareas.style.display = "block";
58 tabareas.childNodes[0].style.display = 'block';
59 }
60 }
61
62 //对当前结点的父节点(所有)设置属性
63 var parentnode = document.getElementById(tabpageid);
64 while(true)
65 {
66 parentnode = parentnode.parentNode;
67
68 if(parentnode == null)
69 {
70 break;
71 }
72
73 if((parentnode.className =="tab-page")||(parentnode.className =="tabarea"))
74 {
75 parentnode.style.display = 'block';
76 }
77 }
78
79 document.getElementById(tabpageid).style.display = 'block';
80 document.getElementById(tabpageid+"_li").className = 'CurrentTabSelect';
81 document.getElementById(tabpageid+"_li").childNodes[0].className="current";
82 }
83
84
85 function getElementsByClassName(strClassName, strTagName, oElm)
86 {
87 var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
88 var arrReturnElements = new Array();
89 strClassName = strClassName.replace(/\-/g, "\\-");
90 var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
91 var oElement;
92 for(var i=0; i<arrElements.length; i++){
93 oElement = arrElements;
94 if(oRegExp.test(oElement.className)){
95 arrReturnElements.push(oElement);
96 }
97 }
98 return (arrReturnElements)
99 }
本文标签:
很赞哦! ()
上一篇:discuz目录结构文件说明示例
相关教程
图文教程
DiscuzX1.5利用添加好友处存储xss进行蠕虫worm扩散
DiscuzX1.5在添加好友的地方有处存储xss,借助此处xss跟用户交互可以进行蠕虫指数扩散,位置在添加好友处x完之后的效果,点击后触发。
Discuz编辑器代码总结
1.[ b]文字:在文字的位置可以任意加入您需要的字符,显示为粗体效果。2.[ i]文字:在文字的位置可以任意加入您需要的字符,显示为斜体效果。
Discuz中SESSION机制讲解
在Discuz!X中一如继往的,SESSION并没有使用PHP自带的SESSION机制,而是系统的一套自带的机制。在数据库中可以看到有两个SESSION表:
ubuntu下搭建Discuz的步骤方法
环境:我用桥接方式创建了一个ubuntu16的虚拟机,ip为192.168.1.11)然后解压到某个目录,例如在根目录建立个新目录mkdir discuz,然后解压到此目录中unzipDiscuz_X3.2_SC_UTF8.zip -d discuz/
相关源码
-
(响应式H5)帝国cms7.5文章新闻博客模板带会员中心本模板基于帝国CMS内核开发,为新闻资讯、个人博客及作品展示类网站设计。采用响应式布局技术,确保在手机、平板和电脑等不同设备上都能获得良好的浏览体验。查看源码 -
(自适应)帝国cms7.5模板自媒体文章新闻博客为帝国CMS7.5设计的响应式模板,采用H5技术构建现代化内容展示框架。通过智能断点检测技术实现手机、平板、PC三端适配查看源码 -
(自适应)蓝色基建施工工程建筑集团网站pbootcms模板下载为工程建筑、基建施工类企业打造的PbootCMS模板,采用现代化设计理念,突出企业实力与项目展示,帮助建筑类企业快速建立专业在线门户。查看源码 -
(自适应响应式)电子数码科技产品介绍带留言网站模板下载为电子产品企业设计的展示系统,集成智能产品对比器、参数规格表和展示模块。支持消费电子、智能设备等多级分类展示,内置产品技术参数数据库。查看源码 -
(PC+WAP)绿色产品环保设备垃圾桶厂家公司网站pbootcms模板为垃圾桶生产商、环保设备企业打造的高端响应式门户模板,基于PbootCMS开源内核深度开发。采用HTML5自适应架构,无缝实现PC与手机端数据实时同步与交互优化查看源码 -
帝国cms7.5模板生活常识美食女性时尚综合资讯门户源码本模板为帝国cms7.5生活资讯类网站设计,以天奇生活网为参考原型,涵盖生活常识、美食烹饪、女性时尚等多元化内容板块。采用响应式布局设计,适配各种终端设备,为访客提供优质的阅读体验。模板结构清晰合理,内容展示层次分明,符合生活类网站的用户需求。查看源码
| 分享笔记 (共有 篇笔记) |
