国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

《Asp.Net Forums2.0深入分析》之 Asp.Net Forums是如何實現代碼分離和換

2024-07-10 12:56:47
字體:
來源:轉載
供稿:網友
在visual studio中開發web項目,web 窗體頁由兩部分組成:視覺元素(html、服務器控件和靜態文本)和該頁的編程邏輯。 一般將這兩個組成部分分別存儲在一個單獨的文件中。可視元素在一個 .aspx 文件中創建,而代碼位于一個單獨的類文件中(.aspx.vb 或 .aspx.cs)。或者有時候也會在同一文件中創建視覺元素和代碼。

而在asp.net forums的web窗體頁中沒有找到我們熟悉的.aspx.cs文件,也沒有發現任何c#代碼,取而代之是一個個控件,代碼在哪里?!

下面將以login.aspx為例詳細說明asp.net forums是如何實現代碼分離和換皮膚的:
首先我們看看login.aspx在兩種皮膚樣式下的運行效果
(theme:default)(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并轉到對應文件:

(該圖告訴您如何快速的查找控件對應的文件)
 
從代碼中看到的該控件是從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接口,是因為在開發模板化控件時,應實現該接口以避免同一頁上的命名沖突。
在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實現可以換皮膚的控件一文的例子,也許有助您理解:)




發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乌拉特前旗| 平舆县| 虞城县| 鄄城县| 贺兰县| 绥化市| 那坡县| 天全县| 二连浩特市| 禄丰县| 丽江市| 原平市| 调兵山市| 永新县| 玛曲县| 名山县| 灵川县| 清镇市| 阜新市| 江华| 瑞安市| 繁峙县| 大名县| 普定县| 银川市| 萍乡市| 江源县| 灵川县| 连城县| 米脂县| 方山县| 丰顺县| 界首市| 新丰县| 班戈县| 兰州市| 崇文区| 垣曲县| 夏邑县| 称多县| 承德市|