接上篇…首先讓我們來看如何創建一個我們先前討論的textbox
我們已經知道需要創建的textbox有一個文本值與之對應:
文本值在label標簽中
可選的值放在Textbox中
可選的驗證信息(validation message)
如果上面3個條件都能滿足,肯定也能滿足我們在part1裡的那5個條件.還有一些錦上添花的是可以通過屬性來指定textbox是否包裹在li標簽內以及textbox是否是readonly模式.這樣我們便能更好的在vIEw page中代碼復用。下面的代碼包含所有HtmlText(譯者按:繼承AbstractHtmlVIEwObject對象,在part1的類圖中)對象所有的屬性:
PRivate readonly string mLabelText;
private readonly bool mCreateLabel;
private readonly object mValue;
private readonly string mValidationMessage;
private readonly bool mCreateValidationMessage;
private readonly bool mCreateLi;
private readonly bool mReadonly;
public HtmlText(
VIEwRequestContext requestContext, string name, string labelText, objec
string validationMessage, bool @readonly, bool createLi, object attribu
: base(requestContext, name)
{
mLabelText = labelText;
mCreateLabel = !string.IsNullOrEmpty(mLabelText);
mValidationMessage = validationMessage;
mCreateValidationMessage = !string.IsNullOrEmpty(validationMessage);
mCreateLi = createLi;
mReadonly = @readonly;
Attributes = attributes;
object valueToAssign = value;
if (valueToAssign == null)
{
// see if the ModelState has a value for this
valueToAssign = GetModelStateValue(name, typeof(string));
}
mValue = valueToAssign;
} 在構造函數中,我們我們存入一系列私有變量中並初始化了會在StartVIEw方法內使用的一個bool類型,除此之外你可以發現這裡開始使用GetModelStateValue方法.目前為止我們先不過多討論這個方法,這個方法會在後面提到。在參數傳入構造器之前我們注意到:
value參數的類型是object
object類型的attributes參數被傳入
之所以把Value參數定義為object類型是因為這樣可以使用戶更容易使用並且和ASP.net MVC Helpers的執行方式保持一致。attributes參數可以被調用者來擴展生成的HTML。比如說,你想將textbox的maxlength屬性設置為5,你只需要傳入匿名類型”new {maxlength=5}“.input標簽會將這個匿名類型轉換為Html屬性maxlength=5.這同時也符合ASP.Net MVC中Html Helper現有擴展方法的使用方式.每一個View helper對象都應該支持這種行為以便具有更大的靈活性.在這個類中剩下的兩個方法就是從父類繼承來的StartView和EndVIEw方法了.
StartView和EndVIEw的定義如下:
public override void StartVIEw()
{
HttpResponseBase httpResponse = RequestContext.HttpResponse;
TagBuilder HtmlLiTagBuilder = new TagBuilder("li");
if (mCreateLi)
{
httpResponse.Write(HtmlLiTagBuilder.ToString(TagRenderMode.StartTag));
}
// write out label if provided
if (mCreateLabel)
{
TagBuilder labelTag = new TagBuilder("label");
labelTag.Attributes.Add("for", Name);
labelTag.SetInnerText(mLabelText);
httpResponse.Write(labelTag.ToString(TagRenderMode.Normal));
}
string stringValue = string.Empty;
if (this.mValue != null)
{
stringValue = Convert.ToString(this.mValue, CultureInfo.CurrentCulture);
}
if (this.mReadonly)
{
TagBuilder textTag = new TagBuilder("span");
textTag.AddCSSClass("readonly-text");
textTag.SetInnerText(
Convert.ToString(this.mValue, CultureInfo.CurrentCulture));
httpResponse.Write(textTag.ToString(TagRenderMode.Normal));
}
else
{
// Use MVC helpers to create the actual text box
httpResponse.Write(RequestContext.HtmlHelper.TextBox(
Name, this.mValue, Attributes));
}
if (this.mCreateLi)
{
httpResponse.Write(HtmlLiTagBuilder.ToString(TagRenderMode.EndTag));
}
}
public override void EndVIEw()
{
// Not needed for this element
}
在StartVIEw方法中有很多值得注意的地方,讓我們逐個討論。首先是我們使用System.Web.Mvc.TagBuilder來生成HTML,而不是直接寫Html標簽。TagBuilder只能在ASP.Net MVC中使用並且我推薦在生成HTML中必須使用TagBuilder而不是直接寫Html標簽,下面是TagBuilder的類圖:
下表是TagBuilder中一些方法的說明:
名稱 描述
AddCssClass 加入CSS的class名稱,如果class已經存在,則後來加入的會和原來的class一起生效
MergeAttribute 這個方法用於添加或者更新tag的屬性,這個方法有一個接受replaceExisting參數的重載,默認情況下已經定義的屬性不會被重載。
MergeAttributes 同上,只是可以在一個方法內添加或更新所有屬性.
SetInnerText 設置標簽內的文本
ToString 被重載。用於生成相應的html代碼,TagRenderMode枚舉類型會控制如何生成Html標簽.
在上面表格的ToString那行,TagRenderMode枚舉用於控制TagBuilder生成Html標簽的方式,TagRenderModel如下所示:
TagRenderModel 結果示例
Normal <div name=”Sample01”>Some content here</div>
StartTag <div name=”Sample01”>
EndTag </div>
SelfClosing <div name=”Sample01” />
根據你想創建的HTML標簽和你如何使用它,你會發現使用TagRenderModel可以創建出任何你想創建出的HTML.在前面提到的StartVIEw方法內你會發現TagRenderModel被依據不同的條件設置成StartTag,Normal和EndTag等不同的的類型.如果你給InnerHTML屬性賦值並用StartTag和EndTag生成它你必須要記住InnerHtml不會被自動生成,你還必須顯式的使用InnerHtml屬性本身。下面我們來討論如何創建HtmlHelper擴展方法。
-------------------------------------------
待續…