还记得duwamish吗?在那里面,一些页面由用户控件组成,而其所承担的逻辑处理都是在控件内部完成的,这样是把控件做为单独的逻辑模块使用。在forum里,我们又看到了这种处理方法,并且,更加的复杂和灵活,用来实现皮肤主题的更换。
通过前面的两篇笔记,已经大致了解了forum的控件使用,下面就做一次该方面的总结。(广告时间:之所以先关注这个,是因为我想把下一版的stella里使用这种模式。请大家期待大概两个星期后完成的Stella Forum V 1.2)
在forum中,页面由“模块控件”(我自己起的名字,呵呵)组成,这些模块控件其实是由负责呈现内容的的用户控件和负责进行逻辑处理的自定义空间共同组成的。这样的隔离处理是为了可以方便的更换用户控件达到更换皮肤的目的,逻辑操作都一样,所以后面的自定义控件就不需要改动。还有比较重要的是,页面上标记的都是自定义控件,这个也不会因皮肤的更换而修改。
实际上,forum里的页面和用户控件很少有codebehind的代码,因为逻辑即处理都交给自定义控件了。这样可以达到一种即插即用的效果,比如那个登陆模块,你可以随心的放到任何地方,而不用修改页面处理代码。
主题文件都放在统一的目录下,加载的时候会直接到该目录下找相应的文件。
拿登陆控件来分析,主要设计这三个控件:
Skin-Login.ascx
AspNetForums.Controls.Login
AspNetForums.Controls.SkinnedForumWebControl
Skin-Login提供了登陆时需要呈现的html,包括文本框、按钮等,Login用来初始化Login并对提交事件进行处理,SkinnedForumWebControl是Login的基类,主要作用是动态加载需要使用的用户控件。
CreateChildControls方法扮演了重要的角色,SkinnedForumWebControl里有两个方法LoadSkin和InitializeSkin都是在CreateChildControls被使用。详细的说,先是LoadSkin加载要使用的用户控件,然后在InitializeSkin里对这个控件进行初始化。注意InitializeSkin是vietual的,这个方法的实现主要是在个各子类(也就是具体的自定义控件,在这里是Login)。在InitializeSkin重要的是对各种事件的订阅,比如登陆时要点按钮,对点击事件的订阅就在这里。过程就是先用FindControl找到相应的控件,然后在处理。
要加载的具体控件是在子类中先定好,然后在基类中加载。CreateChildControls的触发顺序是先子类后基类。
系统怎么知道该加载哪个主题?这个一开始有个默认设置,然后用户可以自己更改需要的主题。在用户控制面板中可以看到该选项。
接下来的问题,在用户面板中可以选择需要哪个主题,那系统是怎么知道都有哪些主题?我们可以看提供选择的那个控件是AspNetForums.Controls.ThemeDropDownList,在该控件里完成了该项功能,在这里给出一行代码:
string[] dirs = Directory.GetDirectories( context.Request.PhysicalApplicationPath + ForumConfiguration.GetConfig().ForumFilesPath + "\\themes" );
这样,forum是直接到themes文件夹下看有哪些主题包,然后显示出来供选择。大家可以到官网http://bbs.hidotnet.com下一个主题包,然后直接解压到这个文件夹,这样新的主题就可以用了。刚才我下了那个龙翔的主题,也没有看安装说明什么的,直接就把里面的default文件夹改名成lxSkin,然后放到themes里,就直接可以用了,用户在选择的时候会看到两个选择default和lxSkin。