<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    注銷

    注銷

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      112 隨筆 :: 7 文章 :: 18 評論 :: 0 Trackbacks

    一、 ???????????? DataGrid 控件中的 ViewState

    ?? Asp.Net 中,我們使用最多的恐怕就是 DataGrid 列表控件了。這個控件的功能的卻非常強大,也非常好用。它不但可以實現任意的格式化選擇,而且還可以動態進行分頁、排序、添加按鈕、動態編輯等功能。可以說, DataGrid 控件已經實現了我們需要的大部分功能。

    ?? 遺憾的是,上面說的很多非常實用的功能,大部分需要 ViewState 的支持,就是說 DataGrid 控件需要通過 ViewState 來保存控件的狀態的,如果我們關閉了 ViewState ,即在 HTML 代碼中使用了 EnableViewState ="False" 屬性,那么,上面的所有有用的功能我們將無法使用。

    ?? ViewState 的缺點也是很大的,就是 DataGrid 會把所有的數據源中的數據存放到 ViewState 中。 DataGrid 是一個列表控件,它存放在 ViewState 中的數據包括了列表中所有單元格( Cell )中的數據,更加可恨的是,即時我們打開了分頁功能,它也要把所有的沒有顯示出的數據源中的數據放到 ViewState 里面,如果不在數據庫端控制數據量大小的話, DataGrid 控件實際上是把數據庫表中所有數據統統都存放在 ViewState 中。直接后果就是 Asp.Net 生成發送到客戶端的源 Html 代碼異常龐大。

    ?? 大家知道, Asp.Net 中, ViewState 實際上是一個名稱 / 值對的字典,為了正確在各種編碼的網頁中保存,將 ViewState 序列化后又進行了 Base64 編碼。這將更加加大 ViewState 的數據量。

    ?? 我試驗了一下,一個包括 5000 條記錄的數據庫,如果不在數據庫端控制數據量的話,直接使用 Select * From TableName 這樣的 Sql 語句綁定數據的話,一個 Asp.Net 動態網頁(僅有一個 DataGrid 控件的測試頁)的 ViewState 60k 之多。而這樣一個網頁放到公共 Web 網站,緩慢的網頁下載速度將會使大部分人望而卻步,使用 56k 貓上網的人就更不要提了,根本無法訪問這樣的網頁,等待的時間將不可忍受。

    ?? 所以大部分有 Asp.Net 開發經驗的開發者,如果不使用 DataGrid 的高級功能的話,一般是把 EnableViewState ="False" 屬性給加入的,還有就是使用自己的分頁控件,不使用 DataGrid 提供的分頁功能,這將取消 DataGrid ViewState ,大大減少最終生成的 Html 的代碼量。

    ?

    二、 DataGrid 中必須使用 ViewState 的一些功能

    ?? 不錯,很多情況下我們僅需要 DataGrid 的顯示列表數據的功能,或者使用自己的分頁功能,這種情況下可以使用 EnableViewState ="False" 屬性,但是如果我們需要使用 DataGrid 的動態編輯、按鈕列,或者要訪問 DataGrid 的索引項時,我們必須把 DataGrid ViewState 打開,這將不可避免的出現 ViewState 數據量過大的現象,但是我們沒有辦法。

    ?? 我大略統計了一下 DataGrid 中需要使用 ViewState 的一些功能屬性,它們都必須使用 ViewState ,而這些屬性我們很多情況下都必須使用:

    DataGrid.CurrentPageIndex???????????????????? DataGrid 分頁的頁索引

    DataGrid.DataKeys???????????????????????? ??? 取每個記錄的鍵值

    DataGrid.EditItemIndex??????????????????????? 編輯項的索引

    DataGrid.Items??????????????????????????????? DataGrid 中行的集合

    DataGrid.PageCount??????????????????????????? DataGrid 分頁的總頁數

    ?

    而在使用 DataGrid 內置事件時,傳遞事件參數的 DataGridItemEventArgs DataGridCommandEventArgs DataGridSortCommandEventArgs DataGridPageChangedEventArgs 類更加要使用 DataGrid ViewState ,否則它們將無法工作。

    ?? 這里我給一個簡單的示例,在 DataGrid 中加入一個 CheckBox 列,這使當頁面回發的時候我可以獲取 DataGrid 的鍵值。但是如果關閉 ViewState 的話,此功能無法使用。

    ?

    ?

    Html

    < Asp:DataGrid ID=”myDataGrid”Runat=”Server”DataKeyField=”ID” AutoGenerateColumns=”False”>

    ??? < Columns >

    ?????? < asp:TemplateColumn >

    ?????????? < ItemTemplate >

    ????????????? < Asp:CheckBox ID=”myBox”Runat=”Server”/>

    ?????????? </ ItemTemplate >

    ?????? </ asp:TemplateColumn >

    ??? </ Columns >

    </ Asp:DataGrid >

    < br />< br />

    < Asp:Button ID= ”bntSubmit” Runat= ”Server” Text= ”OK” />

    ?

    Code

    private void btnSubmit_Click(object sender, System.EventArgs e)

    {

    ??? CheckBox cb;

    ??? string str;

    ??? for(int i=0;i<myDataGrid.tems.Count;i++)

    ??? {

    ?????? cb = (CheckBox)myDataGrid.Items[i].Cells[2].FindControl("myBox");

    ?????? if(cb.Checked)

    ?????????? str += myDataGrid.DataKeys[myDataGrid.Items[i].ItemIndex].ToString();

    ??? }

    ??? // 此時 str 變量就是 DataGrid 中選中行的數據庫鍵值。

    }

    ?

    上面的代碼使用很成功,不過如果在 DataGrid 中使用了 EnableViewState=”False” 屬性,那么上面的代碼根本無法起作用。


    ?

    三、去掉 ViewState DataGrid 無用數據

    ? ? 終于說到正題了,我這篇文章說的就是怎樣去掉 ViewState 中的無用數據,而保留有用的數據。文章寫到這里,我們可以很明顯的看出來, DataGrid 保存在 ViewState 中的數據分為兩個部分,一部分是保存索引用的,就是 DataKeys DataItems 這樣的屬性使用的數據,我們把它稱之為索引數據。還有一部分是 DataGrid 中數據源的內容,我們稱之為列表數據。

    ? ? 我們如果把實際上無用的列表數據從 ViewState 中去除,這樣可以大大減小頁面 ViewState 的數據大小,使用 DataGrid ViewState 數據量太大的根本原因就是列表數據存放在 ViewState 中。

    ? 我在微軟的 .Net Framework SDK 文檔中沒有找到關閉列表數據 ViewState 的任何內容,就是說微軟沒有給出 DataGrid 運行時的任何調用順序和內部的工作機制。沒辦法,我使用了一個工具來獲得 DataGrid 的內部工作流程,發現它在數據綁定初始化的時候,生成了一個叫 DataGridTable 的控件對象,這個對象是繼承 System.Web.UI.WebControls.Table 控件的。而且這個對象是最先加入(使用 Controls.Add() 方法) DataGrid 中的。而且 ViewState 中的 DataGrid 列表數據也是這個控件加入到 DataGrid 中的。實際上, ViewState 中的 DataGrid 的單元格中的數據實際上是 System.Web.UI.WebControls.Table 控件的 SaveViewState() 方法給加進去的。這些數據很多情況下是不需要的。

    ?? 好,原因找到了,解決問題就好辦了,因為微軟已經給出了控制 DataGrid 中子控件的方法。我們既然知道 DataGridTable 控件是 DataGrid 中最先生成的控件,那么我們通過 DataGrid.Controls 屬性就可以直接獲取 DataGrid 中子控件的引用,獲得引用后就可以控制子控件了。解決方法就是在數據綁定的時候,設置 DataGrid DataGridTable 控件的 EnableViewState 屬性為 False 就可以了。

    代碼如下:

    首先必須重寫 DataGrid.ItemDataBound DataGrid.ItemCreated 事件,我們用它們來控制在向客戶端寫 html 之前 DataGrid 的動作。這兩個事件任選其一,都可以實現效果。我們使用 ItemDataBound 事件來寫例子, DataGrid 示例 ID myDataGrid

    [C#]

    首先在頁面初始化中的 InitializeComponent() 方法內加入事件的委托:

    private void InitializeComponent()

    {

    ??? this.myDataGrid.ItemDataBound +=

    new DataGridItemEventHandler(this.myDataGrid_ItemDataBound);

    }

    然后在 myDataGrid_ItemDataBound 方法內加入控制代碼:

    private void myDataGrid_ItemDataBound(object sender, DataGridItemEventArgs e)

    {

    ??? myDataGrid.Controls[0].EnableViewState = false;

    }

    ?

    [VB.Net]

    Private Sub myDataGrid_ItemDataBound(sender As Object,e As DataGridItemEventArgs) _

    Handles myDataGrid.ItemDataBound

    ?

    ??? myDataGrid.Contols.Item(0).EnableViewState = False

    ?

    End Sub

    ?

    好了,使用 DataGrid 時,把上面的代碼加入,將減小使用 DataGrid ViewState 90% 的數據量。而且, DataGrid 中許多使用 ViewState 的功能絲毫不少,豈不是兩全其美?

    ?

    注意:

    1. 上面說的法子有一種情況下不能使用,就是使用 DataGrid 的內部分頁功能時,重寫 DataGrid.PageIndexChanged 事件時,調用 DataGridPageChangedEventArgs 時,必須把所有的 ViewState 打開,包括列表數據,關閉任何的 ViewState ,都將導致 DataGridPageChangedEventArgs 的索引丟失,無法分頁。

    不過這個缺點很好解決,很多人已經寫了自定義的分頁控件,這些控件是不需要 DataGrid 的任何數據的。可以提供非常完美的分頁功能。

    2. (重要)我春節的這幾天對上面說的辦法進行了詳細的測試,發現上面的辦法確實有效,可以大大的減少 aspx 頁面的 ViewState 的數據量,但是這個辦法在使用上有一個注意的地方,否則會出現數據無法顯示的毛病。

    我一直在奇怪,微軟寫 DataGrid 為什么要加入一個 DataGridTable 類,而且還要把所有的數據庫數據存放在 ViewState 中。經過測試我才發現,這是因為有了 System.Web.UI.Page.IsPostBack 屬性的緣故。我們經常喜歡利用 Page.IsPostBack 屬性檢測頁面是否是第一次運行,如下代碼:

    private void Page_Load(object sender, System.EventArgs e)

    {

    ??? if(!Page.IsPostBack)

    ??? {

    ?????? // 頁面第一次運行 , 執行數據綁定

    ?????? SqlConnection conn = new SqlConnection(“...”);

    ?????? SqlCommand comm = new SqlCommand(“...”,conn);

    ?????? ...

    ?????? ...

    ?????? myDataGrid.DataBind() // 數據綁定

    ??? }

    }

    當然,網頁執行第一次時, DataGrid 的內容正常顯示,而使用了上面的去除 ViewState 方法后,頁面如果回發處理, DataGrid 的內容將會消失。我才明白 DataGrid DataGridTable 把數據存放在 ViewState 內的用意。微軟的設計是非常嚴謹的,他們的用意就是當使用 Page.IsPostBack 屬性時,僅訪問一次數據庫就可以永久保持 DataGrid 的數據(在不離開此頁面的情況下),數據存放的地點就是頁面的 ViewState 中。這樣頁面回發后, DataGrid 就可以從 ViewState 中重新生成 DataGrid 的顯示內容,無需訪問數據庫。所以說微軟以犧牲客戶下載的速度( ViewState 數據量)來保證服務器的資源,大家都知道頻繁訪問數據庫對服務器的資源消耗很大。

    所以,使用上面減少 DataGrid ViewState 數據的法子是可行的,但是必須使所有的頁面回發處理都必須進行數據綁定,否則 DataGrid 無法獲得數據庫內容,也無法獲得 ViewState 中保存的數據,那么回發后 DataGrid 將無法顯示任何內容。

    總結,使用上面減少 ViewState 的辦法可以大大加快客戶端的下載顯示速度,但是頻繁的數據庫訪問將加大服務器的壓力;使用 ViewState 可以減輕服務器的壓力,但是又加大了客戶端的下載時間,它們是互相矛盾的。所以開發者要根據實際情況選擇是否使用 DataGrid.Controls[0].EnableViewState=false; 的法子,如何選擇,大家請自己斟酌。


    posted on 2006-11-21 17:08 注銷..... 閱讀(439) 評論(0)  編輯  收藏 所屬分類: .net摘要
    主站蜘蛛池模板: 亚洲AV无码一区二区三区人| 国产亚洲一区二区三区在线| 久久综合亚洲鲁鲁五月天| 99久久精品毛片免费播放| 亚洲中文字幕无码中文字在线| 看成年女人免费午夜视频| 无码专区一va亚洲v专区在线 | 亚洲精品高清在线| 含羞草国产亚洲精品岁国产精品 | 婷婷亚洲天堂影院| 一级一级一片免费高清| 国产aⅴ无码专区亚洲av麻豆 | 一个人免费观看视频www| 亚洲国产品综合人成综合网站| 国产电影午夜成年免费视频 | 四虎亚洲精品高清在线观看| 好吊妞在线成人免费| 亚洲精品精华液一区二区| 在线看片无码永久免费aⅴ| 朝桐光亚洲专区在线中文字幕 | 一区二区三区福利视频免费观看| 亚洲精品私拍国产福利在线| 成人免费观看一区二区| 国产成人亚洲综合网站不卡| 国产片免费在线观看| 国产精品免费久久久久影院| 国产∨亚洲V天堂无码久久久| 18禁美女裸体免费网站| 亚洲AV无码专区在线电影成人 | 亚洲乱码无限2021芒果| 国产在线a不卡免费视频| av片在线观看永久免费| 久久精品国产亚洲av四虎| 国产片AV片永久免费观看| 亚洲国产无线乱码在线观看 | 免费人成在线观看视频高潮| 91亚洲自偷手机在线观看| 岛国大片免费在线观看| 久久久久久久久久免免费精品| 亚洲日本乱码一区二区在线二产线| 免费观看男人免费桶女人视频|