今天被問到一個小問題,我想大部分以 ASP.NET 開發 Web App 的朋友都會碰到,就順便把它記在這裡。

問題很簡單:如何讓 Panel 的標題置中?

如果有指定 Panel 控制項的 GroupingText 屬性,Panel 的左上角就會顯示這個 GroupingText 屬性的值,看起來就像是 Panel 的標題。可是 Panel 沒有屬性可以讓我們控制這個標題要靠左、置中、還是靠右。

解法也很簡單:利用 Page 的 Render 事件,在網頁傳回前端瀏覽器之前,先取得要產生好的網頁內容,修改之,然後才送回前端瀏覽器。

先說明一下解問題的過程。碰到這個問題,第一個先找找看 Panel 是否已經提供相關的屬性,免得自己兜一大圈才發現元件本來就有這個功能了。若元件本身既有的功能無法解決問題,接著我會去看看網頁的 Control Tree,看看這個控制項是不是有包含什麼子控制項,可以讓我用加入 HTML 標籤的屬性的方式解決(呼叫控制項的 Attributes.Add 方法)。把 @Page 的 Trace 功能打開之後,發現 Panel 的 Control Tree 裡面還是沒有什麼線索。那只好使出最後的手段,也就是在網頁傳回瀏覽器前端之前,自行修改 ASP.NET 產生的網頁內容。

可是要修改哪裡?怎麼修改?

我們可以先利用瀏覽器的檢視原始碼功能,看一下 ASP.NET Panel 控制項會產生什麼相對應的 HTML tag。你可以看到類似下面的結果: 

<div id="Panel1" style="height:82px;width:481px;">
 <fieldset>
  <legend>
   這是 Panel 的標題
  </legend>          
 </fieldset>
</div>

從 HTML 內容可以看到,Panel 控制項的標題文字是由 <legend> 標籤來顯示。因此如果我們可以讓 <legend> 裡面的文字置中,就能解決我們的問題了。我們可以先用記事本編輯一個簡單的測試網頁,試著在 <legend> 標籤裡加上 align="center" 屬性,看看是不是我們想要的。例如:

<legend align="center"> ... </legend>

測試之後發現結果正是我們預期的,剩下來的問題就是如何用程式來加工最終產生的網頁內容了。

傳回前端瀏覽器的網頁內容,其實是 ASP.NET 網頁上面的所有控制項生成 (render) HTML 標籤的結果。Page 有一個 Render 方法,它的工作就是令網頁上所有子控制項產生 (render) 對應的 HTML 標籤。因此,我們只要改寫 Page 的 Render 方法,在裡面對網頁內容動點手腳就行了。程式碼很簡單,就不多解釋了,如下:

    protected override void Render(HtmlTextWriter writer)
    {
        StringBuilder sb = new StringBuilder();
        HtmlTextWriter myWriter = new HtmlTextWriter(new StringWriter(sb));

        // 先呼叫父類別的 Render 方法,把產生的 HTML 內容寫入至我們的 sb 字串緩衝區中保存.
        base.Render(myWriter);

        // 加工 sb 的內容,把 <legend> 標籤加上置中對齊的屬性.
        sb.Replace("<legend>", "<legend align='center'>");

        // 最後再輸出至前端瀏覽器.
        writer.Write(sb.ToString());
    }

That's it!