闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤濠€閬嶅焵椤掑倹鍤€閻庢凹鍙冨畷宕囧鐎c劋姹楅梺鍦劋閸ㄥ綊宕愰悙鐑樺仭婵犲﹤鍟扮粻鑽も偓娈垮枟婵炲﹪寮崘顔肩<婵炴垶鑹鹃獮鍫熶繆閻愵亜鈧倝宕㈡禒瀣瀭闁割煈鍋嗛々鍙夌節闂堟侗鍎愰柣鎾存礃缁绘盯宕卞Δ鍐唺缂備胶濮垫繛濠囧蓟瀹ュ牜妾ㄩ梺鍛婃尰閻熝呭垝鐠囧樊鍚嬪璺猴功閿涚喖姊绘笟鍥у闁告娲熷畷鍫曨敆婢跺娅栨繝鐢靛Т閿曘倝骞婇幇鐗堝€垮┑鍌氭啞閻撶喖骞栭幖顓炵仯缂佸鏁婚弻娑氣偓锝傛櫇閸斿秶绱掗崒姘毙㈡顏冨嵆瀹曞ジ鎮㈤崫鍕闂傚倷绀侀幉锟犲礉閹达箑绀夌€光偓閸曨偆鍔﹀銈嗗笒閸婂綊寮抽渚囨闁绘劘灏欑粻濠氭煕閳轰礁顏€规洘枪椤﹀绱掗悩瀹犲妞ゎ亜鍟存俊鍫曞幢濡も偓椤洭姊虹粙鍖℃敾婵炶尙鍠庨锝夊箹娴e摜顓哄┑鐘亾閸ㄥ綊鏌婇敐鍛殾闁诡垶鍋婂顏堟⒒婵犲骸澧婚柛鎾跺枛瀵鎮㈢喊杈ㄦ櫓闂佷紮绲介張顒勫闯閺夋娓婚柕鍫濆暙閻忣亝淇婇銏犳殭闁伙絿鍏橀幃銏ゆ偂楠烆兘鏅犻弻鏇熷緞閸績鍋撻弴鈶哄顫濋懜鐢靛幗闂佺粯鏌ㄩ幗婊堟儗婵犲嫮纾肩紓浣姑ù顔锯偓瑙勬礃瀹€鎼佺嵁閹烘绠婚柛鎾茶兌濡插洦绻濆▓鍨灍闁挎洍鏅犲畷婊冣槈閵忊晜鏅e┑鐐叉▕娴滄繈鍩涢幋锔界厵缂佸鐏濋銏ゆ煟閹惧崬鍔﹂柡灞剧☉铻i柤濮愬€楅悡澶愭倵鐟欏嫭绀冮柛銊ユ健閻涱喖螣閼测晝锛滃┑鈽嗗灣缁垶鎮甸弽顓熲拻濞撴埃鍋撻柍褜鍓涢崑娑㈡嚐椤栨稒娅犻柟缁㈠枟閻撴瑦銇勯弴妤€浜剧紓浣哄У閻楃姴顕i锕€绠荤紓浣姑禍褰掓⒑閼测斁鎷¢柛鎿勭畵瀹曘儳鈧綆鍋傜换鍡涙煟閹板吀绨婚柍褜鍓氶悧鏇$亱婵炶揪缍€椤宕h箛娑欑厪闁割偅绻嶅Ο鍫ユ煛娴i潻韬柡宀嬬節瀹曞爼濡烽妷褌鐥梻浣瑰▕閺€杈╂暜閹烘绠掗梻浣瑰缁诲倿骞婅箛娑樼疅闁告縿鍎崇壕鐓庮熆鐠洪缚瀚伴柛鏂款儏鑿愰柛銉戝秷鍚銈冨灪濞茬喐鎱ㄩ埀顒勬煃閵夈儱甯犳繛锝庡櫍濮婄粯鎷呯粵瀣異闂佸摜濮靛畝绋跨暦閹达箑围濠㈣泛锕ラ悗顒勬⒑閸涘﹤濮﹂柛鐘崇墱婢规洟宕楅崗鐓庡伎濠碘槅鍨板ḿ锟犲传濞差亝鐓熼柟鍨缁夘喗鎱ㄦ繝鍕笡闁瑰嘲鎳樺畷顐﹀Ψ椤喓鍔岄埞鎴﹀煡閸℃ぞ绨诲┑鐐点€嬬换婵嬬嵁閸愵喗鍊烽柣鎴炆戝▍鍥⒑缁嬫寧婀扮紒瀣灦缁傚秴螖閸涱喒鎷洪梻鍌氱墛娓氭危閹绢喗鐓涢柛娑卞枤閻帡鏌熼鍡欑瘈闁诡喓鍨藉畷妤呮嚃閳轰礁绠伴梻鍌欑劍閹爼宕曢鈧鎻掆槈濞嗘埈娴勫┑鐘诧工閻楀﹪鎮¢崘顏呭枑婵犲﹤鐗嗙粈鍫熺箾閸℃鐛滈柤鏉挎健濮婃椽顢楅埀顒傜矓閹绢喗鍊块柛顭戝亖娴滄粓鏌熼崫鍕ラ柛蹇撶焸閺屾盯鎮㈤崫銉ュ绩闂佸搫鐬奸崰鏍х暦濞嗘挸围闁糕剝顨忔导锟�     濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻橀弻锝夊箣閿濆棭妫勯梺鍝勵儎缁舵岸寮诲☉妯锋婵鐗婇弫楣冩⒑閸涘﹦鎳冪紒缁橈耿瀵鏁愭径濠庢綂闂佺粯锚濡﹤螞瀹€鍕拺閺夌偞澹嗛ˇ锕傛煥閺囥劋閭€殿喖顭烽崹楣冨箛娴e憡鍊梺纭呭亹鐞涖儵鍩€椤掆偓绾绢參顢欓幇鐗堚拻闁稿本鑹鹃埀顒佹倐瀹曟垿宕卞☉妯虹€梻渚囧墮缁夊瓨顢婇梻浣告啞濞诧箓宕规导鏉戠闁逞屽墴濮婃椽妫冨ù銈嗙洴瀹曘劑顢涘顒傜憿缂傚倸鍊搁崐鎼佸磹瀹勬噴褰掑炊閳哄啰顦╂繛鏉戝悑濞兼瑧澹曠憴鍕瘈闂傚牊渚楅崕蹇涙煢閸愵亜鏋涢柡灞诲妼閳规垿宕遍埡鍌傃囨⒑閸濆嫭鍣洪柣鎿勭節瀵鈽夊Ο閿嬵潔闂佸憡顨堥崑鐐烘倶瀹ュ鈷戦柛锔诲幖閸樻潙霉濠婂啰鍩f鐐插暙铻栭柛鎰ㄦ櫅閺嬪倿姊洪崨濠冨闁告挻鐩棟闁靛ň鏅滈埛鎴犵磽娴h偂鎴﹀箚閸垻纾肩紓浣贯缚缁犳挻銇勯弴顏嗙ɑ缂佺粯绻傞~婵嬵敇閻愭壆鐩庨梻浣藉吹閸嬬偟绮欓崼銉ョ劦妞ゆ巻鍋撻柛妯荤墬缁旂喖寮撮悙鈺傛杸闂佺粯鍔栧ḿ娆撴倶閿斿浜滈煫鍥ч瀹撳棙顨ラ悙宸剶闁轰礁鍟撮崺鈧い鎺戝€搁ˉ姘舵煕瑜庨〃鍡涙偂濞戙垺鐓曢柕澶堝灪濞呭懘鏌$€n偅鈷掔紒杈ㄥ浮閹晠鎳¢妶鍥ㄦ瘒闂備礁鎼惉濂稿窗閹捐鐒垫い鎺嶈兌閳洖鐣濋敐鍛仴妤犵偛锕畷姗€顢欓悾灞藉箺闂傚⿴鍋勫ú銈夋晝閵夈儮鏋嶅┑鐘叉处閻撴稓鈧厜鍋撻悗锝庡墰琚︽俊銈囧Х閸嬬偛鐜婚崸妤€鐒垫い鎺戝濞懷囨煙鐠囇呯瘈鐎规洘鑹鹃埥澶愬閳锯偓閹锋椽姊洪崨濠勭畵閻庢凹鍘奸敃銏″鐎涙ḿ鍘介梺鍐叉惈閿曘倝鎮橀敃鍌涚厽婵炴垵宕▍宥団偓瑙勬礀閻栧ジ銆佸Δ鍛劦妞ゆ帒鍊婚惌鍡涙煕瀹€鈧崑鐐烘偂閺囩喓绡€闂傚牊绋戦鈺呮煕閺冣偓缁捇寮婚敓鐘插窛妞ゆ挻绮屾禒顔尖攽椤旂》鍔熺紒顕呭灦楠炲繘宕ㄧ€涙ɑ鍎梺鑽ゅ枑婢瑰棝顢曟總鍛娾拻濞达絿鍎ら崵鈧梺纭咁嚋缁绘繈鐛崘顔肩<闁绘劦浜栭崑鎾寸瑹閳ь剙顕f禒瀣╅柕澹懐宓佹繝鐢靛Х閺佸憡鎱ㄧ€电硶鍋撳☉鎺撴珖缂佽京鍋為幆鏃堝煢閳ь剟寮ㄦ禒瀣厽闁归偊鍓欑痪褔鏌嶇紒妯荤闂囧绻濇繝鍌氼伀闁活厽甯楅〃銉╂倷閺夋垹浼岄梺纭呮珪缁捇骞冨▎鎾寸劵婵炴垶姘ㄥ▔鍧楁⒒閸屾瑦绁版い顐㈩槸閻e嘲螣鐞涒剝鐏冨┑鐐村灦閻熝囥€呴柨瀣瘈濠电姴鍊搁弳濠囨煛閳ь剚绂掔€n偆鍘撻梺瀹犳〃缁€渚€寮抽悙鐑樼厪闁搞儯鍔庣粻鏍煙娓氬灝濡界紒缁樼箞瀹曘劑顢氶崨顒€鎽嬮梻鍌欒兌閹虫挸顕i崼鏇炵闁告劘灏欓弳锕傛煟閺冨倵鎷¢柡浣告喘閺岋綁寮崑鍐茬秺瀵煡骞栨担鍏夋嫼闁荤姴娲ゅ鍫曞船婢跺浜滄い鎰╁焺濡叉悂鎮¢妶澶嬬厽闁哄倹宕橀懡锛勭磽閸屾稒鐨戦柟鍙夋倐瀵噣宕煎☉鎺戜壕濞达絽澹婂ḿ鈺呮偣鏉炴壆绉块柕濞炬櫆閻撱儵鏌¢崒姘变虎闁抽攱妫冮弻锝夋晝閳ь剟鎮ч幘鎰佹綎婵炲樊浜滅粻褰掓煟閹邦厼绲诲┑顔肩焸濮婃椽宕ㄦ繝鍐弳缂備礁顦伴幐鎶藉春閵忕媭鍚嬪璺衡看濞煎﹪姊洪棃娑氬婵☆偄鐭傞獮蹇撁洪鍛幗闂佺粯锚閸樻牠鎳滈鍫熺厱闁哄倽鍎荤€氫即鏌嶇拠鑼ф鐐叉喘閹囧醇閵忕姴绠ラ梻鍌欑閹诧繝宕归鐐茬9闁哄稁鍋€閸嬫挸顫濋悙顒€顏�

45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:Asp.Net Forums实现代码分离和换的方法

Asp.Net Forums实现代码分离和换的方法

2016-09-07 04:14:28 来源:www.45fan.com 【

Asp.Net Forums实现代码分离和换的方法

在Visual Studio中开发Web项目,Web 窗体页由两部分组成:视觉元素(HTML、服务器控件和静态文本)和该页的编程逻辑。 一般将这两个组成部分分别存储在一个单独的文件中。可视元素在一个 .aspx 文件中创建,而代码位于一个单独的类文件中(.aspx.vb 或 .aspx.cs)。或者有时候也会在同一文件中创建视觉元素和代码。

而在Asp.Net Forums的Web窗体页中没有找到我们熟悉的.aspx.cs文件,也没有发现任何C#代码,取而代之是一个个控件,代码在哪里?!

下面将以login.aspx为例详细说明Asp.Net Forums是如何实现代码分离和换皮肤的:

首先我们看看login.aspx在两种皮肤样式下的运行效果

Asp.Net Forums实现代码分离和换的方法(Theme:default)Asp.Net Forums实现代码分离和换的方法(Theme:ElectricMidnight)

只是更改了一下Asp.Net Forums的默认皮肤,同样是Login.aspx,显示的是两种不同的皮肤样式。先回想一下VS.Net中,先不论换皮肤功能,如果我们要实现一个登陆页面,那么我们在Aspx或Ascx页中将输入帐号密码的TextBox、登陆的Button拖入,在编辑区双击Button,写上对Button点击事件处理的代码,多么方便,大部分代码都由VS.Net为我们完成了。

我们再来看Login.aspx的源码:

<%@ Import Namespace="AspNetForums.Components" %>

<%@ Register TagPrefix="Forums" Namespace="AspNetForums.Controls" Assembly="AspNetForums.Controls" %>

<%@ Register TagPrefix="mp" Namespace="MetaBuilders.WebControls.MasterPages" Assembly="MetaBuilders.WebControls.MasterPages" %>

<mp:ContentContainer runat="server" id="MPContainer" MasterPageFile="~/Themes/MasterPage.ascx">

<mp:Content id="MainContent" runat="server">

<p align="center">

<Forums:NavigationMenu DisplayTitle="true" id="Navigationmenu1" runat="server" />

<br />

<br />

<br />

<Forums:Login runat="server" id="PostView1" />

</p>

</mp:Content>

</mp:ContentContainer>
注:其中 <mp:***> ,这个是一个第三方控件,其目的是为了保证界面的一致性,提取页面间的重复代码。

从源码中我们没有看到任何构成Login.aspx页面效果的TextBox、Button等基本元素。甚至没有发现一行C#代码,不过如果您对页面控件比较熟悉不难发现原来Asp.Net Forums中将登陆的界面封装为了控件(在此对页面控件并不作专门介绍,如果您对控件相关知识还比较陌生的话,强烈推荐您查阅相关资料或书籍)。 原来登陆界面的实现就是在<Forums:Login runat="server" id="PostView1" />控件中,从
<%@ Register TagPrefix="Forums" Namespace="AspNetForums.Controls" Assembly="AspNetForums.Controls" %>
我们可以知道Login控件对应的类应该为:AspNetForums.Controls.Login,在VS.Net中,切换到类视图,找到AspNetForums.Controls.Login并转到对应文件:

Asp.Net Forums实现代码分离和换的方法

(该图告诉您如何快速的查找控件对应的文件)

从代码中看到的该控件是从SkinnedForumWebControl类继承的:

public class Login : SkinnedForumWebControl { // 从 SkinnedForumWebControl 基类继承

......

}

我们还是先看看基类SkinnedForumWebControl。
using System;

using System.Drawing;

using System.Collections;

using System.Collections.Specialized;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using AspNetForums;

using AspNetForums.Components;

using System.ComponentModel;

using System.IO;

using System.Web.Security;

using AspNetForums.Enumerations;

namespace AspNetForums.Controls {

[

ParseChildren(true)

]

/// <summary>

/// 几乎Asp.Net Forums中所有控件的基类,继承自WebControl,并实现INamingContainer接口

/// </summary>

public abstract class SkinnedForumWebControl : WebControl, INamingContainer {

ForumContext forumContext = ForumContext.Current;

string skinFilename = null;

string skinName = null;

string returnURL = null;

ForumMode mode = ForumMode.User;

public SkinnedForumWebControl() {

// 使用的皮肤——如果是匿名用户,则使用系统默认样式

//

if (forumContext.User.IsAnonymous) {

skinName = Globals.Skin;

}

else {

skinName = forumContext.User.Theme;

}

}

/// <summary>

/// 当开发复合服务器控件或模板服务器控件时,必须重写此方法。

/// 通知使用基于合成的实现的服务器控件创建它们包含的任何子控件,以便为回发或呈现做准备。

/// </summary>

protected override void CreateChildControls() {

Control skin;

// 装载用户控件

skin = LoadSkin();

// 初始化控件

InitializeSkin(skin);

Controls.Add(skin);

}

/// <summary>

/// 通过SkinName和SkinFilename找出用户控件文件的路径,装载该用户控件后的Control对象

/// </summary>

/// <returns></returns>

protected Control LoadSkin() {

Control skin;

// 用户控件文件所在位置

string skinPath = Globals.GetSkinPath() + "/Skins/" + SkinFilename.TrimStart('/');

string defaultSkinPath = Globals.ApplicationPath + "/Themes/default/Skins/" + SkinFilename.TrimStart('/');

// 必须要有SkinFilename属性

if (SkinFilename == null)

throw new Exception("You must specify a skin.");

// 从用户控件文件获取 UserControl 对象。

try {

skin = Page.LoadControl(skinPath);

}

catch (FileNotFoundException) {

// 如果没有找到指定皮肤的用户控件文件,装载默认皮肤下的控件文件

try {

skin = Page.LoadControl(defaultSkinPath);

}

catch (FileNotFoundException) {

throw new Exception("Critical error: The skinfile " + skinPath + " could not be found. The skin must exist for this control to render.");

}

}

return skin;

}

/// <summary>

/// 初始化控件,并绑定控件数据

/// </summary>

/// <param name="skin"></param>

protected abstract void InitializeSkin(Control skin);

/// <summary>

/// 用户控件文件(*.ascx)路径

/// </summary>

public string SkinFilename {

get {

return skinFilename;

}

set {

skinFilename = value;

}

}

/// <summary>

/// 皮肤名

/// </summary>

protected string SkinName {

get {

return skinName;

}

set {

skinName = value;

}

}

public ForumMode Mode {

get { return mode; }

set { mode = value; }

}

}

}
从代码中可以看出,基类SkinnedForumWebControl继承自WebControl类并实现了INamingContainer接口。既然是自定义控件,自然就是从WebControl类继承。之所以实现INamingContainer接口,是因为在开发模板化控件时,应实现该接口以避免同一页上的命名冲突。

Asp.Net Forums实现代码分离和换的方法在SkinnedForumWebControl中有两个重要的属性:SkinName 和 SkinFilename,分别表示皮肤名和用户控件文件路径。在Asp.Net Forums2.0中,在Web目录下有一个Themes目录,每种皮肤对应一个目录,例如default、ElectricMidnight,每个皮肤文件夹下有三个文件夹:image、Skins和style,分别用来存放该皮肤下对应的图片文件、用户控件文件(*.ascx)和样式表Css文件。通过这两个属性,我们可以知道用户控件文件(*.ascx)的真实路径,例如我们的SkinName是default,SkinFilename是skin-login.ascx,那么用户控件的路径是Themes/default/skins/skin-login.ascx,同理,如果我们将皮肤样式换成ElectricMidnight,那么用户控件的路径将是 Themes/ElectricMidnight/skins/skin-login.ascx。

还有两个重要的方法,一个是LoadSkin(),在该方法中,首先根据上面介绍的两个属性找出用户控件文件的路径,然后通过Page.LoadControl(defaultSkinPath)方法,从用户控件文件中获取 UserControl 对象。这也就是为什么皮肤不同,页面样式就不同,因为随着皮肤的不同,我们Load的用户控件文件也不同,我们只要将用户控件文件样式设置的不一样,就可以随着皮肤的不同显示的样式也不一样。

 

但是光这些还不够,我们还需要识别ascx页中的页面控件。例如在skin-login.ascx中,我们必须知道哪个输入框是帐号的,那个输入框是密码的,知道用户是否点击了登陆按钮。回想VS.Net中,IDE自动帮我们把这些控件根据ID识别出来,在IDE中双击按钮,就可以直接加上响应点击事件的代码,多么方便。但是现在我们该如何?……

基类中还有一个抽象的InitializeSkin(Control skin)方法,所有继承自SkinnedForumWebControl的控件都必须override该方法,因为我们可以在这个方法中来初始化控件,在LoadSkin()方法中我们已经通过Page.LoadControl(defaultSkinPath)方法返回了一个UserControl,现在我们在InitializeSkin(Control skin)中通过Control.FindControl 方法,在UserControl中搜索指定的服务器控件,并对控件进行绑定数据和事件。还是以Login控件为例,摘取AspNetForums.Controls.Login类中的部分代码如下:

public class Login : SkinnedForumWebControl { // 从 SkinnedForumWebControl 基类继承

string skinFilename = "Skin-Login.ascx"; // 默认皮肤文件

TextBox username; // 帐号输入框

TextBox password; // 密码输入框

Button loginButton; // 登陆按钮

}

public Login() : base() {

if (SkinFilename == null)

SkinFilename = skinFilename; // 定义默认的皮肤文件

}

// 重写 InitializeSkin 初始化

override protected void InitializeSkin(Control skin) {

// 查找ascx页中ID是username的textbox控件

username = (TextBox) skin.FindControl("username");

// 查找ascx页中ID是password的textbox控件

password = (TextBox) skin.FindControl("password");

// 找到登陆按钮

loginButton = (Button) skin.FindControl("loginButton");

loginButton.Click += new System.EventHandler(LoginButton_Click); // 绑定登陆按钮的Click事件

loginButton.Text = ResourceManager.GetString("LoginSmall_Button");

}

在skin-login.ascx中,我们的每个控件都有一个ID,例如用户名输入框的ID是username,这样,我们就可以在重写InitializeSkin(Control skin)的时候,利用username = (TextBox) skin.FindControl("username");这样的方法来一个个找到对应用户控件文件中的控件。并可以对绑定数据和事件,例如:loginButton.Click += new System.EventHandler(LoginButton_Click),绑定登陆按钮的Click事件。

综上所述,Asp.Net Forums就是通过自定义控件来实现代码分离的,并通过在控件中动态装载用户控件文件(*.aspx)来实现换皮肤功能的。当您在看Asp.Net Forums2.0源代码的时候,再也不要被<Forums:NavigationMenu DisplayTitle="true" id="Navigationmenu1" runat="server" />这样的代码所吓倒,直接切换到类视图,找到对应的类:AspNetForums.Controls.NavigationMenu,从类代码中……

如果您还不是很理解,您可以自己研读一下Asp.Net Forums2.0的源码,如果您觉得太复杂,请看模拟Asp.Net Forums实现可以换皮肤的控件一文的例子,也许有助您理解:)

 

本文地址:http://www.45fan.com/a/question/73422.html
Tags: 实现 ASP.NET Forums
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部