使用User Control做HTML產生

來源:互聯網
上載者:User

使用User Control做HTML產生

User
Control大家肯定不會陌生,在使用ASP.NET的過程中,除了aspx頁面,最常見的就莫過於ascx了。ascx是一個有獨立邏輯的組件,提供
了強大的複用特性,合理使用,能夠大大提高開發效率。通過User
Control直接產生HTML內容其實已經是一個比較常用的技巧了(尤其在AJAX時代),不過網路上這方面的內容比較少,很多人還是在苦苦地拼接字元
串,因此在這裡我通過一個執行個體簡單介紹一下這個技巧。  對一個對象(文章,圖片,音樂,etc.)進行評論是應用中最常見的功能之一。首先,我們定義一
個Comment類,以及其中會用到的“擷取”方法:
public partial class Comment
{

public DateTime CreateTime { get; set; }

 

public string Content { get; set; }
}



public partial class Comment
{

private static List<Comment> s_comments = new List<Comment>

{

new Comment

{

CreateTime = DateTime.Parse("2008-5-1"),

Content = "今天天氣不錯"

},

new Comment

{

CreateTime = DateTime.Parse("2008-5-2"),

Content = "挺風和日麗的"

},

new Comment

{

CreateTime = DateTime.Parse("2008-5-3"),

Content = "我們下午沒有課"

},

new Comment

{

CreateTime = DateTime.Parse("2008-5-1"),

Content = "這的確挺爽的"

}

};

 

public static List<Comment> GetComments(int pageSize, int pageIndex, out int totalCount)

{

totalCount = s_comments.Count;

 

List<Comment> comments = new List<Comment>(pageSize);

 

for (int i = pageSize * (pageIndex - 1);

i < pageSize * pageIndex && i < s_comments.Count; i++)

{

comments.Add(s_comments);

}

 

return comments;

}
}
為了顯示一個評論列表,我們可以使用一個使用者控制項(ItemComments.aspx)來封裝。自然,分頁也是必不可少的:
<asp:Repeater runat="server" ID="rptComments">

<ItemTemplate>

時間:<%# (Container.DataItem as Comment).CreateTime.ToString() %><br />

內容:<%# (Container.DataItem as Comment).Content %>
</ItemTemplate>

<SeparatorTemplate>

<hr />

</SeparatorTemplate>

<FooterTemplate>

[color=blue]<hr />

</FooterTemplate>[/color]
</asp:Repeater>


<% if (this.PageIndex > 1)

{ %>

<a href="/ViewItem.aspx?page=<%= this.PageIndex - 1 %>" title="上一頁">上一頁</a>
<% } %>

<% if (this.PageIndex * this.PageSize < this.TotalCount)

{ %>

<a href="/ViewItem.aspx?page=<%= this.PageIndex + 1 %>" title="上一頁">下一頁</a>
<% } %>
public partial class ItemComments : System.Web.UI.UserControl
{

protected override void OnPreRender(EventArgs e)

{

base.OnPreRender(e);

 

this.rptComments.DataSource = Comment.GetComments(this.PageSize,

this.PageIndex, out this.m_totalCount);

this.DataBind();

}

 

public int PageIndex { get; set; }

 

public int PageSize { get; set; }

 

private int m_totalCount;

public int TotalCount

{

get

{

return this.m_totalCount;

}

}
}

然後再頁面(ViewItem.aspx)中使用這個組件:
<div [color=red]id="comments">[/color]<demo:ItemComments
ID="itemComments" runat="server"
/>[color=blue]<[color=blue]/[/color]div[color=blue]>[/color][/color]
public partial class ViewItem : System.Web.UI.Page
{

protected void Page_Load(object sender, EventArgs e)

{

this.itemComments.PageIndex = this.PageIndex;

}

 

protected int PageIndex

{

get

{

int result = 0;

Int32.TryParse(this.Request.QueryString["page"], out result);

 

return result > 0 ? result : 1;

}

}
}

開啟ViewItem.aspx之後效果如下:時間:2008/5/1 0:00:00
內容:今天天氣不錯 時間:2008/5/2 0:00:00
內容:挺風和日麗的 時間:2008/5/3 0:00:00
內容:我們下午沒有課 下一頁
  這張頁面的功能非常簡單,那就是察看評論。當前評論的頁碼會使用QueryString的page項進行指定,然後在ViewItem.aspx裡獲
取到並且設定ItemComments.ascx控制項的屬性。ItemComments控制項會根據自身屬性來擷取資料,進行綁定,至於顯示內容,全都定義
在ascx中了。由於需要分頁功能,這個評論控制項中還包含了上一頁和下一頁的連結,他們連結的目標很簡單,就是ViewItem.aspx頁,並且加上頁
碼的Query String而已。
  功能是完成了,不過用著用著忽然覺得不妥,為什麼呢?因為我們在翻頁,或者使用者發布評論的時候,整張頁面都重新整理了。這可不好,要知道可能
ViewItem頁中還有其他幾個顯示部分,它們可是不變的。而且如果其他幾個部分也需要分頁,那麼可能就需要保留頁面上每一部分的當前頁碼,這樣開發的
複雜性還是比較高的。
  那麼我們不如用AJAX吧。無論是使用者察看評論時進行翻頁還是發表評論,都不會對頁面上的其他內容造成影響。要開發這個功能,自然需要伺服器端的支援,那麼該怎麼做呢?一般我們總是有兩種選擇:

伺服器端返回JSON資料,在用戶端操作DOM進行呈現。
伺服器端直接返回HTML內容,然後在用戶端設定容器(例如上面id為comments的div)。
  不過無論採用哪種做法,“呈現”的邏輯一般總是另寫一遍(第一次的呈現邏輯寫在了ItemComments.ascx中)。如果使用第1種做法,那麼
呈現邏輯就需要在用戶端通過操作DOM進行呈現;如果使用第2種做法,那麼就要在伺服器端進行字串拼接。無論哪種做法都違背了DRY原則,當
ItemComments.ascx裡的呈現方式修改時,另一處也要跟著修改。而且無論是操作DOM元素還是拼接字串維護起來都比較麻煩,開發效率自然
也就不高了。
  如果我們能夠直接從ItemComments控制項獲得HTML內容該多好啊——那麼我們就這麼做吧。請看如下代碼(GetComments.ashx):
public class GetComments : IHttpHandler
{

public void ProcessRequest(HttpContext context)

{

context.Response.ContentType = "text/plain";

 

ViewManager<ItemComments> viewManager = new ViewManager<ItemComments>();

ItemComments control = viewManager.LoadViewControl("~/ItemComments.ascx");

 

control.PageIndex = Int32.Parse(context.Request.QueryString["page"]);

control.PageSize = 3;

 

context.Response.Write(viewManager.RenderView(control));

}

 

public bool IsReusable { ... }
}

  很簡單的代碼,不是嗎?建立對象,設定屬性,然後通過Response.Write輸出而已。實在沒什麼大不了的——不過關鍵就在於ViewManager類,我們來看一下它是怎麼實現的:
public class ViewManager<T> where T : UserControl
{

private Page m_pageHolder;

 

public T LoadViewControl(string path)

{

this.m_pageHolder = new Page();

return (T)this.m_pageHolder.LoadControl(path);

}

 

public string RenderView(T control)

{

StringWriter output = new StringWriter();

 

this.m_pageHolder.Controls.Add(control);

HttpContext.Current.Server.Execute(this.m_pageHolder, output, false);

 

return output.ToString();

}
}
  ViewManager中只有兩個方法:LoadViewControl和RenderView。LoadViewControl方法的作用是建立一
個Control執行個體並返回,RenderView方法的作用則就是產生HTML了。這個實現方式的技巧在於使用了一個建立的Page對象作為產生控制項的
“容器”,而最後其實我們是將Page對象的整個生命週期運行一遍,並且將結果輸出。由於這個空的Page對象不會產生任何其他代碼,因此我們得到的,就
是使用者控制項產生的程式碼了。
  不過要實現這個AJAX效果,還需要做兩件事情。
  第一,就是簡單修改一下ItemComments控制項中的翻頁連結,讓它被點擊時調用一個JavaScript函數。例如“上一頁”的代碼就會變成:
<a href="/ViewItem.aspx?page=<%= this.PageIndex - 1 %>" title="上一頁"

onclick="return getComments(<%= this.PageIndex - 1 %>);">上一頁</a>
  第二,就是實現getComments這個用戶端方法。在這裡我使用了prototype架構,好處就是能夠用相當簡潔的代碼來做到替換HTML的AJAX效果:
<script type="text/javascript" language="javascript">

function getComments(pageIndex)

{

new Ajax.Updater(

"comments",

"/GetComments.ashx?page=" + pageIndex + "&t=" + new Date(),

{ method: "get" });

 

return false; // IE only

}
</script>
  大功告成。
  其實就像之前所說的那樣,使用UserControl進行HTML代碼產生是一個十分常用的技巧。尤其在AJAX應用越來越普及的情況下,合理使用上
面提到的方式可以方便的為我們的應用添加AJAX效果。而且很多情況下,我們即使不需要在頁面上顯示內容,也可以將內容使用UserControl進行編
輯。因為編寫UserControl比拼接字串的方式無論是在開發效率上還是可維護性上都高出許多。由於這個方式其實使用了WebForms這個久經考
驗的模型,因此在執行效率方面也是相當高的。此外,就剛才的例子來說,使用UserCotrol進行HTML產生還有其他好處:

頁面呈現邏輯只實現了一次,提高了可維護性。
不會影響頁面的SEO,因為在用戶端<a />的href還是有效。
  事實上,WebForms是一個非常強大的模型,所以ASP.NET
MVC的View也使用了WebForms的引擎。通過上面這個例子,我們其實還可以做到其他很多東西——例如用UserControl來產生XML數
據,因為UserControl本身不會帶來任何額外的內容。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.