Tuesday, February 17, 2009 - 文章

GridView的標題列凍結效果

應該有不少人被這麼要求過吧?

"你們做的網頁表格為什麼不能像Excel一樣凍結標題列,底下捲來捲去也不會跑掉?"

前陣子看到一個不錯的Javascript Library,只用一行Code就可以輕鬆做出HTML表格列凍結的效果,剛好部門裡也常有這種需求,我就弄了一個簡單的範例。

大家可以先看Scrollable HTML Table Plugin範例,它本來是個純Javascript Library,Plugin只是做了簡單的包裝,把new ScrollableTable()一列指令再包起來,意義不大,所以我的示範裡只使用webtoolkit.scrollabletable.js,省去額外載入webtoolkit.jscrollable.js的功夫。

弄了一個虛構的DataTable,Bind到GridView上,稍作處理再var t = new ScrollableTable($("#GridView1")[0], 400, 640);,就變成以下的樣子:

完整程式碼如下:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable t = new DataTable();
        t.Columns.Add("序號", typeof(int));
        t.Columns.Add("料號", typeof(string));
        t.Columns.Add("單價", typeof(decimal));
        t.Columns.Add("數量", typeof(int));
        t.Columns.Add("金額", typeof(decimal), "單價*數量");
        Random rnd = new Random();
        for (int i = 0; i < 200; i++)
        {
            t.Rows.Add(
                i + 1, 
                Guid.NewGuid().ToString().Substring(0, 13).ToUpper(),
                rnd.NextDouble() * 100,
                rnd.Next() * 2000);
        }
        GridView1.AutoGenerateColumns = false;
        foreach (DataColumn c in t.Columns)
        {
            BoundField bf = new BoundField();
            bf.DataField = c.ColumnName;
            bf.HeaderText = c.ColumnName;
            if (c.DataType == typeof(decimal))
                bf.DataFormatString = "{0:#,0.00}";
            else if (c.DataType == typeof(int))
                bf.DataFormatString = "{0:#,0}";
            bf.ItemStyle.HorizontalAlign =
                (!string.IsNullOrEmpty(bf.DataFormatString)) ?
                HorizontalAlign.Right : HorizontalAlign.Center;
                
            GridView1.Columns.Add(bf);
        }
        GridView1.DataSource = t;
        GridView1.DataBind();
    }
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
    #GridView1 tr { border: solid 1px #f0f0f0; }
    #GridView1 td, th { padding: 3px; border: solid 1px white; }
    td, th { padding: 3px; border: solid 1px white; }
    #GridView1 thead tr { background-color: #dddddd; }
    .altRow { background-color: #ddddff; }
    </style>
    <script type="text/javascript" src="jquery-1.3.1.js"></script>
    <script type="text/javascript" src="webtoolkit.scrollabletable.js"></script>
    <script type="text/javascript">
        $(function() {
            $("#GridView1 tr:first").wrap("<thead></thead>");
            $("#GridView1 thead").insertBefore("#GridView1 tbody");
            $("#GridView1 tbody tr:odd").addClass("altRow");
            $("#GridView1").attr("cellspacing", "1");
            var t = new ScrollableTable($("#GridView1")[0], 400, 640);
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:GridView ID="GridView1" runat="server" Font-Size="9pt">
    </asp:GridView>
    </form>
</body>
</html>

由於Scrollable HTML Table需要由<thead>, <tbody>區分凍結區及捲動區,而GridView所產生的HTML Table標題列及內容列都放在<tbody>中且無<thead>,因此要做些事後加工,將標題列提取出來,另外放入新增的<thead>中,程式示範了如何jQuery wrap, insertBefore來解決這個問題,都是酷酷地一步到位,蠻值得參考的。

注意: 此解決方案無法跨瀏覽器,目前測試只有IE6, IE7, FF3可用, 不支援IE8, Safari, Chrome, Opera。

【2009-02-18 更新】找到另一個跨瀏覽器且支援標題欄、列凍結的版本,請見: GridView的標題欄、列凍結效果(跨瀏覽器版)

【茶包射手專欄】Vista Mandatory Integrity Level

 

不經一事,不長一智。

從考完NT 4.0 MCSE後,我就鮮少在Windows上下苦功,都是抱持著用到哪學到哪的精神。

今天在Windows 2008(有開UAC)上調Trixie設定時,發現設定結果無法儲存,沒彈出錯誤,但下次開IE就又回到修改前的樣子。

我知道IE7啟用了所謂的Protected Mode,在存取本機資源時設下諸多限制,以防止透過瀏覽器發動的攻擊,這問題八成與權限有關。二話不說,召來茶包一哥進行偵察,果不其然,由Log來看就是權限設定問題。Trixie的設定要寫入Trixie.config.tmp時出現了Access Denied(下圖中紅色部分)。

一般來說,利用Run As Administrator方式跑IE就可以解決問題,但不知什麼原因,我Run As Admin後無法在IE開啟Trixie設定畫面,感覺上設定畫面出現的瞬間就被關掉。於是我試了另一個方式,暫時關掉Protected Mode後,就可以順利儲存設定。(下圖後段的Log即為順利存檔時的對照)

 

在我的腦海中,存取成功與否由權限設定控制,所以我修改了C:\Program Files (x86)\Bhelpuri\目錄的NTFS權限設定,改為EveryOne均可以讀寫。開啟Protected Mode再試一次,ProcMon檢視結果還是顯示Access Denied!!

這就奇了,NTFS權限都全開了,寫檔動作為何還被擋下來? 臨時Google惡補一下,才知道自己Lag大了... 在Vista中(Windows 2008亦然)又多了新的安全防議法寶--Mandatory Integrity Level,不但檔案上可以設NTFS權限控制,又多了第二層控管,資料物件跟Process各有Integrity Level設定,系統絕對禁止卑微低下的Process去接觸高尚尊貴等級的資源,就算該Process是用管理者身份執行的也不例外。

這好比你受邀參加朋友在某間固特異米其林四星餐廳(Bhelpuri\Trixie資料夾)的Party,明明賓客名單上就有你的名字(NTFS安全設定裡已指定權限),卻因為你穿了T恤+牛仔褲+藍白拖鞋(開啟Protected Mode的IE,Integrity Level被標為Low)而被擋在門外。

在此補充另一位MVP的解說,應該就更明白了。

因此,透過Vista中新增的MIC(Mandatory Integrity Level,強制完整性控制功能),為微軟作業系統增加一道新的安全防線。
他進一步解釋,在Vista作業系統裡,包含程序(Process)和其他資源的安全物件(Securable Object)都有畫分完整性級別(Integrity Level,IL)的等級,分成不信任(Untrusted)、低(Low)、中(Medium)、高(High)及系統(System)等5個級別,級別低的程式不能修改級別高的檔案或程式碼。「而一般的使用者登入多為中權限。」邱銘彰說。
摘自: iThome online : : Vista 夠安全嗎?

而Integrity Level的設定無法由Windows檔案總管等UI查得,SysInternals工具組裡有個AccessChk可以顯示,

C:\Program Files (x86)\Bhelpuri>accesschk -d trixie

Accesschk v4.23 - Reports effective permissions for securable objects
Copyright (C) 2006-2008 Mark Russinovich
Sysinternals - www.sysinternals.com

C:\Program Files (x86)\Bhelpuri\Trixie
  Medium Mandatory Level (Default) [No-Write-Up]
  RW Everyone
  RW BUILTIN\Users
  RW NT SERVICE\TrustedInstaller
  RW NT AUTHORITY\SYSTEM
  RW BUILTIN\Administrators

是的,目錄的IL是Default(Medium),Protected Mode下的IE的IL是Low,因而存取遭拒。問題的解法不外乎: 讓IE以非保護模式執行;或開放Trixie目錄允許IL=Low的程式存取,而我打算嘗試後者。

微軟似乎沒有釋出修改IL的工具(更正: 有內建工具icacls可修改IL,見文後說明),除了Call SDK硬幹,網路上大家多用Mark Minasi(Windows技術書作家)自己寫的chml工具。

C:\Program Files (x86)\Bhelpuri>chml trixie

chml v1.011 -- Change Windows Integrity Level
by Mark Minasi (c) 2006-2008 www.minasi.com
"chml -?" for syntax, examples and notes.

trixie's Windows integrity level=unlabeled (medium)

C:\Program Files (x86)\Bhelpuri>chml trixie -i:l

chml v1.011 -- Change Windows Integrity Level
by Mark Minasi (c) 2006-2008 www.minasi.com
"chml -?" for syntax, examples and notes.

Integrity level of trixie successfully set to low.

C:\Program Files (x86)\Bhelpuri>chml trixie

chml v1.011 -- Change Windows Integrity Level
by Mark Minasi (c) 2006-2008 www.minasi.com
"chml -?" for syntax, examples and notes.

trixie's Windows integrity level=low

修改Trixie目錄IL設為為Low,再試一次,Trixie設定在Protected Mode下也可以順利儲存囉!

[2008-02-17 Update] 其實Vista/Windows已有內建的工具可以修改Integrity Level: icacls http://msdn.microsoft.com/en-us/library/bb625965.aspx,謝謝Phoenix補充。

【延伸閱讀】

搜尋

Go

<February 2009>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
1234567
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication