Community Starter Kit是建立在ASP.NET Forums Application(在www.ASP.net网站上可以见到)基础之上的。与Forums Application一样,Community Starter Kit通过外观将用户接口从代码中分割出来。
Community Starter Kit使用如下四种类型的外观:
· 页面外观 - 页面外观用于确定整个页面的布局。例如,页面外观可用于确定区导航菜单的位置。通常,一个社区只选用一个页面外观。
· 内容外观 - 内容外观应用于页面中的内容区域。例如,有一种内容外观用于登陆界面以确定该页面的外观样式。通常,社区中每个页面有一个内容外观相对应。
· 控件外观 - 控件外观用于定制控件的外观样式。例如,区导航控件就是一个外观化的控件。通过将不同的外观应用于该控件,可以改变区导航菜单的外观。
· 模板外观 - 模板外观用于确定控件模板的外观样式(如Repeater控件中的ItemTemplate和HeaderTemplate模板)。不同的注释视图--直线式视图、内嵌视图、嵌套视图,通过不同的模板外观来实现。
每当加载一个Community Starter Kit页面,同时会加载许多个外观来确定该页面的外观。例如,如果你选择了主题Robotico并需要进入登陆页面的话,下面的外观将被加载(这里还不是全部的列表):
· Robotico的页面外观,位于\Themes\Robotico\Skins\PageSkins\Default.ascx;
· 登陆页面的内容外观,位于\Themes\Robotico\Skins\ContentSkins\Users_Login.ascx;
· 区菜单的控件外观,位于\Themes\Robotico\Skins\ControlSkins\Sections_SectionMenu.ascx。
外观具有的可继承性使得外观操作变得更加复杂。如果某个外观不能加载到特定的主题上去,默认主题的外观会加载这很重要,意味着当你创建一个新主题时,你不用为每个页面和控件都创建一个外观。你只需要覆盖你想要修改的外观就可以了。
外观 是作为一个只包含HTML内容和ASP.NET控件(无代码)的ASP.NET用户控件而被执行的。例如,登陆页面的Users_Login.ascx 外观如下所示:
<%@ Control %>
<p>
Login
</p>
Please enter your username and password below.
<br>
If you are a new user, click <a href="Users_Register.aspx">here</a> to register.
<asp:Panel id="pnlInvalidUsername" Runat="Server">
The username you entered is invalid!
</asp:Panel>
<asp:Panel id="pnlInvalidPassword" Runat="Server">
The password you entered is invalid!
</asp:Panel>
<table>
<tr>
<td>Username:</td>
<td><asp:TextBox id="txtUsername" Columns="20" runat="server" /></td>
</tr>
<tr>
<td>Password:</td>
<td><asp:TextBox id="txtPassword" Columns="20" TextMode="Password" runat="server" /></td>
</tr>
<tr>
<td colspan="2"><asp:Button id="btnLogin" runat="server" Text="Login" /></td>
</tr>
</table>
<p>
Click <asp:HyperLink id="lnkPasswordReminder" Runat="Server" Text="here" /> for a password reminder.
</p>
请注意,该外观只包含HTML和ASP.NET控件,如TextBox控件。
Community Starter Kit中的所有页面从根本上说都是继承自基类SkinnedCommunityControl。基类SkinnedCommunityControl规定了控件所需加载的外观的所有细节。
基类SkinnedCommunityControl有一个很重要的属性(property)和一个很重要的方法(method)必须覆盖,即SkinType属性和InitializeSkin方法。SkinType属性是与控件有关的外观的类型:内容外观,控件外观或模板外观。InitializeSkin方法从外观中返回所有的控件,可以在代码中处理控件的属性。
例如,登陆页面对应的类(Login.cs class)如下所示:
Login.cs
namespace ASPNET.StarterKit.Communities {
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using ASPNET.StarterKit.Communities;
using System.Web.Security;
//*********************************************************************
//
// Login Class
//
// Represents the user login page which enables
// users to login to the community.
//
//*********************************************************************
public class Login : SkinnedCommunityControl {
string _skinFileName = "Users_Login.ascx";
TextBox txtUsername;
TextBox txtPassword;
CheckBox chkPersist;
Button btnLogin;
Panel pnlInvalidUsername;
Panel pnlInvalidPassword;
HyperLink lnkPasswordReminder;
//*********************************************************************
//
// Login Constructor
//
// Calls the base SkinnedCommunityControl constructor
// and assigns the default page skin.
//
//*********************************************************************
public Login() : base() {
// Assign a default skin file name
if (SkinFileName == null)
SkinFileName = _skinFileName;
}
//*********************************************************************
//
// SkinType Property
//
// Specifies the skins directory where this page's skin file is located.
//
//*********************************************************************
override protected string SkinType {
get { return "ContentSkins"; }
}
//*********************************************************************
//
// InitializeSkin Method
//
// Retrieves all the controls from the Page Skin
//
//*********************************************************************
override protected void InitializeSkin(Control skin) {
// Find the Username TextBox
txtUsername = (TextBox)GetControl(skin, "txtUsername");
// Find the Password TextBox
txtPassword = (TextBox)GetControl(skin, "txtPassword");
txtPassword.TextChanged += new System.EventHandler(btnLogin_Click);
// Find the Persist Checkbox (Optional)
chkPersist = (CheckBox)GetOptionalControl(skin, "chkPersist");
// Find the Invalid Username Panel
pnlInvalidUsername = (Panel)GetControl(skin, "pnlInvalidUsername");
pnlInvalidUsername.Visible = false;
// Find the Invalid Password Panel
pnlInvalidPassword = (Panel)GetControl(skin, "pnlInvalidPassword");
pnlInvalidPassword.Visible = false;
// Find Login Button
btnLogin = (Button)GetControl(skin, "btnLogin");
btnLogin.Click += new System.EventHandler(btnLogin_Click);
// Find password reminder
lnkPasswordReminder = (HyperLink)GetControl(skin, "lnkPasswordReminder");
lnkPasswordReminder.NavigateUrl = "~/Users_PasswordReminder.aspx";
}
//*********************************************************************
//
// btnLogin_Click Method
//
// Checks username and password against database. If
// everything checks, logins the user.
//
//*********************************************************************
void btnLogin_Click(Object s, EventArgs e) {
bool blPersist = false;
// Determine whether password should be persisted
if (chkPersist != null)
blPersist = chkPersist.Checked;
// Either login or display error message
switch ( UserUtility.LoginUser(txtUsername.Text,txtPassword.Text) ) {
case 0: // Success!
FormsAuthentication.SetAuthCookie(txtUsername.Text, blPersist);
string redirectUrl = FormsAuthentication.GetRedirectUrl(txtUsername.Text, blPersist).ToLower();
if (redirectUrl.IndexOf("users_logout.aspx") == -1)
Context.Response.Redirect(redirectUrl);
else
Context.Response.Redirect(CommunityGlobals.ResolveBase("default.aspx"));
break;
case 1: // Invalid Password
pnlInvalidPassword.Visible = true;
pnlInvalidUsername.Visible = false;
break;
case 2: // Invalid Username
pnlInvalidUsername.Visible = true;
pnlInvalidPassword.Visible = false;
break;
}
}
}
}
Login 类的SkinType属性将与该类相关的外观识别为内容外观。这意味着控件将从Themes 文件夹下的ContentSkins子目录中加载外观。
InitializeSkin方法通过调用GetControl()方法从内容外观中返回所有控件。GetControl()方法是SkinnedCommunityControl基类的一个方法,用以从外观中返回某个特定的控件。在上例中,InitializeSkin方法从内容外观中返回了txtUsername、 txtPassword TextBoxes 和btnLogin Button控件
当btnLogin Button控件从内容外观中返回后,便与btnLogin_Click事件响应相关联。点击登陆按钮后,就会执行btnLogin_Click方法,通过数据库验证用户的身份。
Community Starter Kit 中的所有页面的实现方法都与登陆页面一样。每个页面包含一个类和一个外观。外观 决定了页面的外观,类实现了页面的所有功能。
Community Starter Kit 中的所有页面都通过执行InitializeSkin方法从与页面有关的内容外观中加载控件。当控件加载完毕后,控件的属性可以被修改。
用于生成页面的这种方法的优点在于,仅仅通过为页面加载不同的外观就可以显著地改变页面外观。如果你选择不同的主题—比如Arc, Robotico, Professional –就会有不同的外观与页面相关联,社区站点的外观也就改变了。(以上内容来自MSDN提供的文档(Architecture.htm))
Community Starter Kit的源码我也只是看了半天,也不能清楚的说明到底是如何工作的,但在下面的内容或许会能你点参考
在Skin的.ascx文件中会有这样的写法:<community:SectionMenu CssClass="SectionMenu" Runat="Server">(页面顶部会有这样的语句:<%@ Register TagPrefix="community" Namespace="ASPNET.StarterKit.Communities" Assembly="ASPNET.StarterKit.Communities" %>)。
你可以在类视图中找到SectionMenu类,它同样继承自SkinnedCommunityControl基类,而SkinnedCommunityControl基类是继承自WebControl的,所以页面中的那种写发实际上就是在用一个自己写的WebControl,了解这一点就容易理解了,你可以自己的看看SectionMenu类和SkinnedCommunityControl基类,在基类中重载了CreateChildControls这个方法(通知使用基于合成的实现的服务器控件创建它们包含的任何子控件,以便为回发或呈现做准备(来自.NET2003帮助文档)),它是在CommunityDefault.aspx页面中的Page_Init方法执行完后自动执行的(这个我还不清楚为什么是在这个时候执行)。
诸如加载外观,加载外观里的控件以及绑定数据的操作都是在CreateChildControls方法中完成的。这样一来,页面才算是真正的生成了。
由于我看得也不是很透彻,所以即使是这点简单的描述也难免会有错误,所以有错误请大家尽量的指出来,这样会加快大家学习Community Starter Kit的过程!让我们共同进步!