Dynamic adjust width of controls in web page
今天這一章內容主要提到的是如何動態調整畫面上的物件的width屬性,其實我在這裡想說先提
一個觀念,幫助大家對網頁物件上的做一個釐清,其實這也是gipi大大指導我:
為什麼會是0呢?其實這段程式我想像我這樣比較觀念有點誤解的人會疑惑這樣的結果。不過這
樣的結果是正確的,因為設定Text屬性,它本身是記下你的顯示內容,而Width屬性是設定該物
件要顯示的寬度,從二者屬性特性來看可以發現實際Text屬性內所填的字串長度與物件Width屬
性值是沒有關係的,因為二者完全是提供不同的訴求,所以要直接從物件本身的Width屬性取得
因為Text內容而改變的寬度,結果就是如上圖所示,不可能得到所要的。
那現在問題來了,如果我畫面中有4個物件,其字數長度完全不樣,有些三個字、二個字、四個
字等,如下圖,我透過紅線來說明四個物件的Width不同造成排版的問題:
那該怎麼來調整網頁畫面中的物件Width屬性呢?讓他們可以整理的對齊呢?也許你會想到二個
常見的做法:
(1) 透過Graphic根據String來轉換成相對的Pixcel來調整物件的Width。
1: Bitmap tBitmap = new Bitmap(1, 1);
2: Graphics tGraphics = Graphics.FromImage(tBitmap);
3: Font tFont = new Font("Arial", 12);
4: lblTitle1.Text = "購買人";
5: int tWidth1 = (int)tGraphics.MeasureString(lblTitle1.Text, tFont).Width;
透過「measure string width」keyword去搜尋到如上的程式範例,透過Graphic方法將String
轉換成Pixcel的計算方式,這樣的用法很常用於Windows Application中。但是在Web Applcaiton
是有缺點的,因為Windows Application你可以在產出的時候指定嵌入要使用的顯示字體,例如
程式中的第3行,所以可以正確算出相對的Pixcel,但是到了Web,讀取畫面的是Browser,每種
不同的Browser都有自己支援的字體與顯示方式,因此,這樣的算法就完全失去他的功能了。
(2) 透過JavaScript將實際Render於網頁畫面中的物件Width屬性取出來進行排版。
這樣的做法在Web Application上我想是很常見的,可以透過JavaScript完成Css的調整達到所要的
效果,但是現在又遇到一個問題了,如下的程式碼:
1: var tControlWidths = new Array();
2: for (i = 1; i < 5; i++) {
3: tWidth = document.getElementById("lbl" + i ).offsetWidth;
4: tControlWidths[i] = tWidth;
5: }
6: tControlWidths.sort(); // 排序:大->小
7:
8: for (i = 1; i < 7; i++) {
9: document.getElementById("lbl" + i ).style.width = tControlWidths[0];
10: document.getElementById("lbl" + i ).style.textAlign = "right";
11: }
這一段程式碼中的第9、10行可以正常的影響 IE瀏覽器,但是在Google Chrome或Safari竟然一點
感覺都沒有,甚至用Opera也一樣沒有效果,這是因為我們用了ASP.NET熟悉的元件:Label,因
為它被Render為Span,這樣的Tag設定他的Width是沒有感覺的,因此一下子本來很容易做到的
效果,現在沒有辦法解了。
以上二種方式都是我們在製作Web Application要做畫面動態排版的時候會使用到的技術,但二者之
間都有存在自己一些不完美的地方,因此,在這邊先感謝Pin指導我JQuery的運用與提點了我一個idea,
我們二個想到了一個做法:
「先對每個物件設定一個空的Css Class,接著透過JQuery取出所要排版的物件,再進行Width的設定」
實作方法:
(1) 在asp.net專案檔中新增一個.css檔案,並且引入JQuery檔。然後建立一個空的Class,簡單設定你要的
特效,例如:background-color或text-align,如下:
1: <link href="main.css" rel="Stylesheet" type="text/css" />2: <script src="jquery-1.4.2.min.js" type="text/javascript"/>
(2) 為要進行排版的物件進行格式的定義,以下是透過Table的方式,並且設定要調整那一個<td>的CssClass。
1: <table>
2: <tr>
3: <td class="Cell1"><asp:Label ID="Label1_lbl" runat="server" Text="購買人" CssClass="Cell1"></asp:Label></td>
4: <td><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></td>
5: </tr>
6: </table>
7: <table>
8: <tr>
9: <td class="Cell1"><asp:Label ID="Label2_lbl" runat="server" Text="電話" CssClass="Cell1"></asp:Label></td>
10: <td><asp:TextBox ID="TextBox2" runat="server"></asp:TextBox></td>
11: </tr>
12: </table>
13: <table>
14: <tr>
15: <td class="Cell1"><asp:Label ID="Label3_lbl" runat="server" Text="eMail" CssClass="Cell1"></asp:Label></td>
16: <td><asp:TextBox ID="TextBox3" runat="server"></asp:TextBox></td>
17: </tr>
18: </table>
19: <table>
20: <tr>
21: <td class="Cell1"><asp:Label ID="Label4_lbl" runat="server" Text="送貨日期"></asp:Label></td>
22: <td><asp:TextBox ID="TextBox4" runat="server"></asp:TextBox></td>
23: </tr>
24: </table>
(3) 加上Javascript進行畫面排版的調整,如下程式碼:
1: <script type="text/javascript">
2: $(document).ready(function() {
3: var tMaxWidth = new Array();
4: $("span[id*='_lbl']").each(function() {
5: tMaxWidth.push($(this).width())
6: });
7: tMaxWidth.sort(DescNumber);
8: $(".Cell1").css({ width: tMaxWidth[0] });
9: });
10:
11: function DescNumber(a, b) {
12: return b - a;
13: }
14: </script>
先宣告一個Array來記下畫面中所有的label物件的Width。配合JQuery的Select指定找出html tag為span,
而且id具有_lbl的物件取出Width值,再進行Sort(由大到小排序),最後修改Cell1 css增加width為最大值的
Width。
(4) 執行結果:順利的將所有的label物件進行整理的排列。
以上是介紹一個動態排列物件的方式,因為這樣的好處可以讓在設計Css時,可以按照不同Brower對於字型的
處理自動化的調整Width。不過在這個範例中是使用Table的方式來做修改,如果你把Label物件換成其他的物
件,我想也是可以正常使用的。而且,因為在Mobile Browser上,用戶設備可能是iPhone、Android、Nokia
或Windows Mobile(Phone),它們都有自己的字型,這些都是變動的因素,因此,我是建議用上述的方式來
隨著瀏覽器調整會比較方便。
References:
http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx
http://www.dev102.com/2008/10/09/measure-string-size-in-pixels-c/