asp.net Forums 之控件研究

今天看了一下asp.net Forums,来说说它的皮肤控件。

首先说说它的皮肤控件基类:SkinnedForumWebControl,这个类位于AspNetForums.Controls命名空间下。

代码
#region VSS

/*
* $Header: /HiForums/Controls/BaseClasses/SkinnedForumWebControl.cs 1 05-10-26 15:04 Jacky $
*
* $History: SkinnedForumWebControl.cs $
*
* ***************** Version 1 *****************
* User: Jacky Date: 05-10-26 Time: 15:04
* Created in $/HiForums/Controls/BaseClasses
*
* ***************** Version 1 *****************
* User: Jacky Date: 05-10-21 Time: 14:20
* Created in $/HiForums/Controls/BaseClasses
*
* ***************** Version 3 *****************
* User: Jacky Date: 05-09-20 Time: 19:15
* Updated in $/ASP.NET Forums/Controls/BaseClasses
*/

#endregion

using System;
using System.IO;
using System.Web.UI;
using AspNetForums.Components;
using AspNetForums.Enumerations;

namespace AspNetForums.Controls
{
[
ParseChildren(
true)
]
/// <summary>
/// 皮肤控件基类
/// </summary>
public abstract class SkinnedForumWebControl : Control, INamingContainer
{
#region 成员字段

private ForumContext forumContext = ForumContext.Current;
private string skinFilename = null;
private string skinName = null;
// string returnURL = null;
private ITemplate inlineSkin = null;
private ForumMode mode = ForumMode.User;

#endregion

#region 构造函数

// *********************************************************************
// SkinnedForumWebControl
//
/// <summary>
/// Constructor
/// </summary>
// ***********************************************************************/
public SkinnedForumWebControl()
{
// What skin should be used?
//
if (forumContext.User.IsAnonymous)
{
skinName
= Globals.Skin;
}
else
{
skinName
= forumContext.User.Theme;
}

}

#endregion

#region 子控件创建

// *********************************************************************
// CreateChildControls
//
/// <summary>
/// This event handler adds the children controls.
/// </summary>
// ***********************************************************************/
protected override void CreateChildControls()
{
Control skin
= null;

if (inlineSkin != null)
{
inlineSkin.InstantiateIn(
this);

InitializeSkin(
this);

}
else
{
// Load the skin
skin = LoadSkin();

// Initialize the skin
InitializeSkin(skin);

Controls.Add(skin);
}
}

#endregion

#region 调用皮肤

// *********************************************************************
// LoadControlSkin
//
/// <summary>
/// Loads the names control template from disk.
/// </summary>
// ***********************************************************************/
protected Control LoadSkin()
{
Control skin;
string skinPath = Globals.GetSkinPath() + "/Skins/" + SkinFilename.TrimStart('/');
string defaultSkinPath = Globals.ApplicationPath + "/Themes/default/Skins/" + SkinFilename.TrimStart('/');

// Do we have a skin?
if (SkinFilename == null)
throw new Exception("You must specify a skin.");

// Attempt to load the control. If this fails, we're done
try
{
skin
= Page.LoadControl(skinPath);
}
catch (FileNotFoundException)
{
// Ok we couldn't find the skin, let's attempt to load the default skin instead
try
{
skin
= Page.LoadControl(defaultSkinPath);
}
catch (FileNotFoundException)
{
throw new Exception("错误:皮肤文件 " + skinPath + " 没有找到. 皮肤必须被指定,以用于控件的呈现.");
}
}

return skin;
}

#endregion

#region 皮肤初始化(抽像类)

// *********************************************************************
// InitializeSkin
//
/// <summary>
/// Initialize the control template and populate the control with values
/// </summary>
// ***********************************************************************/
protected abstract void InitializeSkin(Control skin);

#endregion

#region 公有属性:皮肤文件名

// *********************************************************************
// SkinName
//
/// <summary>
/// Allows the default control template to be overridden
/// </summary>
// ***********************************************************************/
public string SkinFilename
{
get { return skinFilename; }
set { skinFilename = value; }
}

#endregion

#region 皮肤名

// *********************************************************************
// SkinName
//
/// <summary>
/// Used to construct paths to images, etc. within controls.
/// </summary>
///
// ********************************************************************/
protected string SkinName
{
get { return skinName; }
set { skinName = value; }
}

#endregion

#region 公有属性:皮肤

public ITemplate Skin
{
get { return inlineSkin; }
set { inlineSkin = value; }
}

#endregion

#region 公有属性:论坛模式

public ForumMode Mode
{
get { return mode; }
set { mode = value; }
}

#endregion
}
}

它继承于Control, INamingContainer,Control是所有控件的基类,而INamingContainer按口标识在 System.Web.UI.Page 对象的控件层次结构内创建新 ID 命名空间的容器控件,也就是说实现了此接口,它能够帮你完成父子控件的命名工作,实现如下效果:“tr1_td1_control1”。

SkinnedForumWebControl基类的主要工作是重写了基类的CreateChildControls方法。

代码
protected override void CreateChildControls()
{
Control skin
= null;

if (inlineSkin != null)
{
inlineSkin.InstantiateIn(
this);

InitializeSkin(
this);

}
else
{
// Load the skin
skin = LoadSkin();

// Initialize the skin
InitializeSkin(skin);

Controls.Add(skin);
}
}


当内部皮肤控件不为空时,加载内部皮肤控件。
注:这个内部皮肤控件是一个ITemplate(模板接口)里面可以放任意服务器端控件。

不然,由LoadSkin()方法加载经子类指定了用户控件名称的皮肤控件初始化后添加到Controls中。

InitializeSkin()是一个abstract方法,由子类来实现数据绑定,注册事件等行为。

LoadSkin方法如下:

代码
protected Control LoadSkin()
{
Control skin;
string skinPath = Globals.GetSkinPath() + "/Skins/" + SkinFilename.TrimStart('/');
string defaultSkinPath = Globals.ApplicationPath + "/Themes/default/Skins/" + SkinFilename.TrimStart('/');

// Do we have a skin?
if (SkinFilename == null)
throw new Exception("You must specify a skin.");

// Attempt to load the control. If this fails, we're done
try
{
skin
= Page.LoadControl(skinPath);
}
catch (FileNotFoundException)
{
// Ok we couldn't find the skin, let's attempt to load the default skin instead
try
{
skin
= Page.LoadControl(defaultSkinPath);
}
catch (FileNotFoundException)
{
throw new Exception("错误:皮肤文件 " + skinPath + " 没有找到. 皮肤必须被指定,以用于控件的呈现.");
}
}

return skin;
}

 基类完成后,我们要做的就是实现各种皮肤的用户控件和子类控件。然后在网页上通过ContentContainer控件来调用。

这就是Asp.Net Forums的换肤原理,欢迎各位达人指正。

原文地址:https://www.cnblogs.com/Jesong/p/1751423.html