
TemplatedWebControl类的源代码
//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
// Copyright (c) Telligent Systems Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommunityServer.Components;


namespace CommunityServer.Controls
{


/**//// <summary>
/// The base class for ALL community server controls that must load their UI either through an external skin
/// or via an in-page template.
/// </summary>
[
ParseChildren( true ),
PersistChildren( false ),
]

public abstract class TemplatedWebControl : WebControl, INamingContainer
{


Composite Controls#region Composite Controls


/**//// <exclude/>

public override ControlCollection Controls
{

get
{
this.EnsureChildControls();
return base.Controls;
}
}


/**//// <exclude/>

public override void DataBind()
{
this.EnsureChildControls();
base.DataBind ();
}

#endregion


External Skin#region External Skin


/**//// <summary>
/// Gets the name of the theme being used.
/// </summary>

protected virtual string ThemeName
{

get
{
return CSContext.Current.User.Theme;
}
}


protected virtual string SkinFolder
{

get
{
return "~/Themes/" + ThemeName + "/Skins/"; //TODO Use correct skin folder
}
}


private String SkinPath
{

get
{
return this.SkinFolder + ExternalSkinFileName;
}
}


/**//// <summary>
/// Gets the name of the skin file to load from
/// </summary>

protected virtual String ExternalSkinFileName
{

get
{
if (SkinName == null)
return CreateExternalSkinFileName(null);

return SkinName;
}

set
{
SkinName = value;
}
}

string skinName;

public string SkinName
{

get
{
return skinName;
}

set
{
skinName = value;
}
}

protected virtual string CreateExternalSkinFileName(string path)

{
return CreateExternalSkinFileName(path, "Skin-" + this.GetType().Name);
}

protected virtual string CreateExternalSkinFileName(string path, string name)

{
if(path != null && !path.EndsWith("/"))
path = path + "/";

return string.Format("{0}{1}.ascx",path,name);
}


private Boolean SkinFolderExists

{

get
{
HttpContext context = HttpContext.Current;

if ( context != null )
{
String folderPath = context.Server.MapPath( this.SkinFolder );
return System.IO.Directory.Exists( folderPath );
}
return true;
}
}


private Boolean SkinFileExists
{

get
{
HttpContext context = HttpContext.Current;

if ( context != null )
{
String filePath = context.Server.MapPath( this.SkinPath );
return System.IO.File.Exists( filePath );
}
return true;
}
}


private Boolean DefaultSkinFileExists
{

get
{
HttpContext context = HttpContext.Current;

if ( context != null )
{
String filePath = context.Server.MapPath( this.DefaultSkinPath );
return System.IO.File.Exists( filePath );
}
return true;
}
}


protected virtual string DefaultSkinPath
{

get
{
return "~/Themes/default/Skins/" + ExternalSkinFileName;
}
}

#endregion


Public Properties#region Public Properties


/**//// <summary>
/// The template used to override the default UI of the control.
/// </summary>
/// <remarks>
/// All serverside controls that are in the default UI must exist and have the same ID's.
/// </remarks>
[
Browsable( false ),
DefaultValue( null ),
Description( "TODO SkinTemplate Description" ),
PersistenceMode( PersistenceMode.InnerProperty ),
]

public ITemplate SkinTemplate
{

get
{
return _skinTemplate;
}

set
{
_skinTemplate = value;
ChildControlsCreated = false;
}
}
private ITemplate _skinTemplate;

#endregion

public override void RenderBeginTag(HtmlTextWriter writer)

{
}

/**//// <summary>
/// No End Span
/// </summary>
/// <param name="writer"></param>
public override void RenderEndTag(HtmlTextWriter writer)

{
//we don't need a span tag
}


/**//// <exclude/>

public override Control FindControl( string id )
{
Control ctrl = base.FindControl( id );

if ( ctrl == null && this.Controls.Count == 1 )
{
ctrl = this.Controls[ 0 ].FindControl( id );
}
return ctrl;
}


/**//// <exclude/>

protected override void CreateChildControls()
{
Controls.Clear();

// 1) A custom theme setting is the most important
Boolean _skinLoaded = false;

if ( !Globals.IsNullorEmpty(ThemeName) )
{

if ( SkinFolderExists )
{

if ( SkinFileExists && this.Page != null )
{
Control skin = this.Page.LoadControl( this.SkinPath );
this.Controls.Add( skin );
_skinLoaded = true;
}
}
}

// 2) Next, look for an inline template

if ( !_skinLoaded && SkinTemplate != null )
{
SkinTemplate.InstantiateIn( this );
_skinLoaded = true;
}

// 3) last resort is the default external skin

if ( !_skinLoaded && this.Page != null && this.DefaultSkinFileExists )
{
Control defaultSkin = this.Page.LoadControl( this.DefaultSkinPath );
this.Controls.Add( defaultSkin );
_skinLoaded = true;
}

// 4) If none of the skin locations were successful, throw.

if ( !_skinLoaded )
{
throw new CSException( CommunityServer.Components.CSExceptionType.SkinNotFound );
}
AttachChildControls();
}


/**//// <summary>
/// Override this method to attach templated or external skin controls to local references.
/// </summary>
/// <remarks>
/// This will only be called if the non-default skin is used.
/// </remarks>
protected abstract void AttachChildControls();

protected override void Render(HtmlTextWriter writer)

{
//SourceMarker(true,writer);
base.Render (writer);
//SourceMarker(false,writer);
}

[System.Diagnostics.Conditional("DEBUG")]
protected void SourceMarker(bool isStart, HtmlTextWriter writer)

{
if(isStart)

{
writer.WriteLine("<!-- Start: {0} -->", this.GetType());
if(System.IO.File.Exists(this.SkinPath))
writer.WriteLine("<!-- Skin Path: {0} -->", this.SkinPath);
else if(SkinTemplate != null)
writer.WriteLine("<!-- Inline Skin: {0} -->", true);
else
writer.WriteLine("<!-- Skin Path: {0} -->", this.DefaultSkinPath);

}
else
writer.WriteLine("<!-- End: {0} -->", this.GetType());
}



}
}

类图:

下面是该类的详细分析:
作用:
/// The base class for ALL community server controls that must load their UI either through an external skin
/// or via an in-page template.
CreateChildControls()方法:
功能说明:
1.如果存在自定义风格设置(custom theme setting)就首先加载该设置
2.如果条件1不满足,就检查是否存在内嵌模板,如果存在,就加载该内嵌模板。
其中内嵌模板由调用该类的方法通过SkinTemplate公共属性来设置
3.如果条件1、2都不满足,就检查是否存在默认皮肤设置文件(DefaultSkinFileExists),如果存在,就加载该设置
4.如果条件1、2、3均不满足,就抛出异常 。
具体代码:
/// <exclude/>
protected override void CreateChildControls() {
Controls.Clear();
// 1) A custom theme setting is the most important
Boolean _skinLoaded = false;
if ( !Globals.IsNullorEmpty(ThemeName) ) {
if ( SkinFolderExists ) {
if ( SkinFileExists && this.Page != null ) {
Control skin = this.Page.LoadControl( this.SkinPath );
this.Controls.Add( skin );
_skinLoaded = true;
}
}
}
// 2) Next, look for an inline template
if ( !_skinLoaded && SkinTemplate != null ) {
SkinTemplate.InstantiateIn( this );
_skinLoaded = true;
}
// 3) last resort is the default external skin
if ( !_skinLoaded && this.Page != null && this.DefaultSkinFileExists ) {
Control defaultSkin = this.Page.LoadControl( this.DefaultSkinPath );
this.Controls.Add( defaultSkin );
_skinLoaded = true;
}
// 4) If none of the skin locations were successful, throw.
if ( !_skinLoaded ) {
throw new CSException( CommunityServer.Components.CSExceptionType.SkinNotFound );
}
AttachChildControls();
}
这里调用的AttachChildControls方法在该类中是个抽象方法:
/// <summary>
/// Override this method to attach templated or external skin controls to local references.
/// </summary>
/// <remarks>
/// This will only be called if the non-default skin is used.
/// </remarks>
protected abstract void AttachChildControls();
SourceMarker(bool isStart, HtmlTextWriter writer)方法:
作用: 输出跟踪调试信息
备注: (1)
[System.Diagnostics.Conditional("DEBUG")]
表明该方法只有在条件编译参数设置为Debug的时候才会执行
(2)在该类中,该方法未被调用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架