熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

常見Datagrid錯誤

2013-11-13 10:27:28  來源: .NET編程 

  摘要學習如何避免在使用 ASPNET Datagrid 控件進行開發時可能發生的一些常見錯誤(本文包含一些指向英文站點的鏈接)

目錄

  可以使用 Datagrid 創建列表數據而沒有使用
忘記在 Page_Load 事件中檢查 IsPostBack
需要更大的靈活性時仍堅持使用自動生成的列
嘗試僅使用控件 ID 來引用 Datagrid 項目中的控件
可以(或應該)使用分頁而沒有使用
忘記在每個 Datagrid 事件中執行 DataBind() 調用從而導致回發
運行時不必要地在 Datagrid 中動態創建 Datagrid 控件或列
持續使用大型 ViewState
使用 ItemDataBound 或 ItemCreated 事件時忘記檢查適當的 ListItemType
需要對生成的 HTML 有更多的控制時過多地使用了 Datagrid(Repeater 也許是更好的選擇)
參考資料

  datagrid 控件是 Microsoft® ASPNET 中功能最強用途最廣的 Web 控件之一這一點已經得到了 ASPNET 權威人士的認同雖然 Datagrid 控件易於使用但同樣易於給使用者帶來麻煩以下是許多人所犯的一些錯誤這些人包括從初學者到富有經驗的 NET 專家您可以看到許多苦悶的使用者在 ASPNET 新聞組和論壇就這些錯誤提出問題遵循本文概述的相當簡單的步驟可以幫助您避免這些錯誤並節約大量的開發時間

可以使用 Datagrid 創建列表數據而沒有使用

  我知道您不會再使用如下所示的代碼但 ASPNET 領域中許多守舊的用戶仍在繼續使用它們

  ResponseWrite(<table>) While MyDataReaderRead() ResponseWrite(<tr>) ResponseWrite(<td>) ResponseWrite(MyDataReader()) ResponseWrite(</td>) ResponseWrite(</tr>) Loop ResponseWrite(</table>)

  可以對以上代碼進行簡化使其僅為

  <asp:datagrid runat=server datasource=MyDataReader/>並調用 databind() 方法即使需要對 HTML 輸出進行特殊的控制您也可以在用戶界面上記錄集的內容重復出現的情況下使用某個數據 Web 控件

忘記在 Page_Load 事件中檢查 IsPostBack

  最常見的錯誤之一是忘記在數據綁定之前檢查頁面的 IsPostBack 條件例如Datagrid 處於Edit(編輯)模式時忽略該項檢查將導致已編輯的值被數據源中的原始值覆蓋然而該規則至少有一個主要的例外請參閱持續使用大型 ViewState

  以下是包含 IsPostBack 檢查的一個典型 Page_Load 事件BindGrid() 是一個例程用於導入並設置 Datagrid 的數據源並調用 databind() 方法

  Sub Page_Load If Not IsPostBack Then BindGrid() End If End Sub

需要更大的靈活性時仍堅持使用自動生成的列

  如果 Datagrid 所處的環境需要任何一種特殊格式或是需要使用 Datagrid 中的其他任何 Web 控件那麼必須關閉 autogeneratecolumns將 autogeneratecolumns 屬性的設置保持為True(默認設置)的做法僅在最簡單的 Datagrid 方案中有效但對幾乎所有實際的應用程序必須將該屬性設置為False並在 Datagrid 聲明的 <columns></columns> 段中明確地指定列Microsoft Visual Studio® NET 用戶可以使用屬性生成器以圖形化的方式創建這些列

注意如果將 AutoGenerateColumns 的設置保持為True並且在 Datagrid 的 <columns> 段中指定了列那麼最終將得到對列的重復設置系統將首先顯示特別聲明的列隨後是所有自動生成的列
嘗試僅使用控件 ID 來引用 Datagrid 項目中的控件

  許多人沒有認識到對於 Datagrid 的 TemplateColumn 下的 ItemTemplate 中的控件(例如帶有MyTextBoxID 的 TextBox 控件)不能在後面的代碼或是在 ASPX 頁面的 <script> 段中用如下所示的代碼來直接調用該控件

  Dim MyValue As String = MyTextBoxText

  該代碼將導致可怕的名稱MyTextBox沒有聲明錯誤

  因為 Datagrid 是由多個行(項目)組成的所以數據源中的每一行實際都會有一個單獨的MyTextBox實例ASPNET 在每個控件的 ID 前面加上該控件層次結構中每個命名容器的 ID這樣 Textbox 將具有唯一的 ID與頁面中所有其他控件的 ID 都不相同例如如果 MyTextBox 處於 DataGrid那麼生成的 ID 將是 DataGrid:_ctl:MyTextBox_ctl代表 MyTextBox 所處的當前行頁面中其他 MyTextBox 實例的 ID 可能是 DataGrid:_ctl:MyTextBoxDataGrid:_ctl:MyTextBox 等等要檢索需要查找的MyTextBox需要對適當的 DataGridItem 調用 findcontrol 方法該 DataGridItem 用作 TextBox 的父命名容器

  html

  <asp:Datagrid runat=server id=Datagrid> <Columns> <asp:TemplateColumn> <ItemTemplate> <asp:TextBox runat=server id=MyTextBox/> </ItemTemplate> </asp:TemplateColumn> </Columns>

  代碼

  Sub DataGrid_UpdateCommand(sender As Object _ e As DataGridCommandEventArgs) Dim MyValue As String = _ CType(eItemFindControl(MyTextBox) TextBox)Text 對 MyValue 執行操作 End Sub

  對 FindControl 調用的結果調用 CType將會把返回值由 Object 類型強制轉換成 TextBox 類型以訪問 Text 屬性

可以(或應該)使用分頁而沒有使用

  用戶未必希望在單個頁面上滾動查看成千上萬條記錄請確保您的應用程序設計合理能夠處理可能會返回大量記錄的情況有關如何在 Datagrid 中實現分頁的信息請參閱 Paging in DataGrid QuickStart Tutorial在 Scott Mitchell 的文章 Creating a Pageable Sortable DataGrid 中可以找到更多的信息

忘記在每個 Datagrid 事件中執行 DataBind() 調用從而導致回發

  一個常見的問題是當我點擊 Datagrid 某一行中的 Edit(編輯)鏈接時頁面回發且不包含任何數據這是什麼錯誤?問題在於數據僅在頁面第一次被調用時綁定到網格在每個 Datagrid 事件(editupdatecancelpage 或 sort)中請確保設置了 Datagrid 的 datasource 屬性(除非已經在 <asp:Datagrid> 聲明中通過聲明的方式進行了設置)並對 Datagrid 調用了 databind() 方法

運行時不必要地在 Datagrid 中動態創建 Datagrid 控件或列

  在某些業務和技術方案中在運行時創建 ASPNET 控件是必要的也是完全合適的例如有時需要在選擇其他頁面選項後才能在運行時確定用戶界面或是要創建一個復合服務器控件其中的每個子控件都需要動態創建因為無法以聲明的方式創建這些子控件如果遇到這些情況請注意提交頁面時不要保留這些動態控件必須在頁面生命周期的早期在每次回發時重新創建動態控件(例如在 page_init 事件中)警言創建控件要早創建控件要勤有關如何動態創建控件的詳細信息請參閱 Microsoft Knowledge Base 文章 HOW TO:Dynamically Create Controls in ASPNET with Visual Basic NET

  然而如果 Datagrid 應用程序中不是一定需要動態創建控件請避免使用該技術以免遇到麻煩盡管可能創建動態 Datagrid但它們會引發各種事件這通常都會令人頭疼換句話說不要動態創建控件以避免因為創建控件使 ASPX 文件變得散亂

持續使用大型 ViewState

  datagrid 控件會在頁面中添加大量的 ViewState這一點令人討厭因為這會導致呈現給用戶的頁面的總體大小急劇增加要使頁面大小不增加最簡單的方法是無論對整個頁面還是單獨對某些特定的控件都禁用 ViewState例如如果頁面不產生回發那麼對整個頁面禁用 ViewState 是安全的否則請對兩次回發之間狀態信息不會發生更改的各個控件禁用 ViewState或者對不需要隱藏字段來跟蹤自身狀態的那些控件禁用 ViewState

  對 Datagrid 控件或包含 Datagrid 的頁面禁用 ViewState 時如果 Datagrid 會啟動回發事件那麼需要執行一些特殊的步驟首先必須在每次回發時在 Page_Load 中重新綁定 Datagrid這有違常規做法(以及上述第二個問題中的描述)但如果禁用 ViewState該步驟是必需的這樣在執行 Page_Load 後可以正確地引發其他 Datagrid 事件如果要處理以下 Datagrid 事件中的任何一部分(或全部)那麼還需要在 ViewState 中手動存儲一些 Datagrid 屬性例如在禁用了 ViewState 的 Datagrid 中進行編輯時只要是在 Page_Load 中第一次綁定 Datagrid 之前重新存儲 EditItemIndex且 Datagrid 處於編輯模式那麼只需將 EditItemIndex 儲存到 ViewState 就夠了(請參閱示例代碼)

  表 Datagrid 事件與 ViewState 的依賴關系

事件 是否依賴於 ViewState? 要存儲在 ViewState 中的字段 itemcreated   無 itemdatabound   無 sortcommand 是 SortExpression editcommand 是 EditItemIndex pageindexchanged 是 CurrentPageIndex selectedindexchanged   無

  清單 啟用編輯排序和分頁但禁用 ViewState 的 Datagrid 的示例代碼

  Sub Page_Load If Not ViewState(EditItemIndex) Is Nothing Then DatagridEditItemIndex = ViewState(EditItemIndex) End If If Not ViewState(CurrentPageIndex) Is Nothing Then DatagridCurrentPageIndex = ViewState(CurrentPageIndex) End If BindGrid() End Sub Sub BindGrid() Dim DV As DataView DV = GetDataSource() DVSort = ViewState(SortExpression) DatagridDataSource = DV DatagridDataBind() End Sub Sub Datagrid_SortCommand(s As Object _ e As DataGridSortCommandEventArgs) ViewState(SortExpression) = eSortExpression BindGrid() End Sub Sub Datagrid_EditCommand(s As Object _ e As DatagridCommandEventArgs) DatagridEditItemIndex = eItemItemIndex ViewState(EditItemIndex) = eItemItemIndex BindGrid() End Sub Sub Datagrid_PageIndexChanged(s as Object _ e As DataGridPageChangedEventArgs) DatagridCurrentPageIndex = eNewPageIndex ViewState(CurrentPageIndex) = eNewPageIndex BindGrid() End Sub

使用 ItemDataBound 或 ItemCreated 事件時忘記檢查適當的 ListItemType

  Datagrid 控件對每個數據行引發兩個事件首次將每行添加到 Datagrid 時將引發 itemcreated 事件將數據綁定到每行時將引發 itemdatabound 事件添加單元格到 Datagrid 的表格輸出時這些事件可以用於控制每個單元格的外觀或內容例如可以基於數值的范圍修改單元格的背景顏色但關鍵是要記住這些事件的引發針對的是所有 Datagrid 項目類型包括頁眉頁腳和分頁程序項目如果執行 itemdatabound 事件期間沒有在引用項目的數據之前仔細檢查項目類型第一個項目(通常是標題行)就將發生錯誤如果 Datagrid 啟用了分頁且將其設置為在頂端顯示那麼第一個項目就會成為分頁程序項目以下示例代碼顯示如何在引用項目數據之前進行正確的 ListItemType 檢查不要忘了 AlternatingItem!

  Sub DataGrid_ItemDataBound(source As Object _ e As DataGridItemEventArgs) If (eItemItemType = ListItemTypeItem Or _ eItemItemType = ListItemTypeAlternatingItem) Then If eItemDataItem(ForumDate) < DateTimeToday Then eItemCells()BackColor = SystemDrawingColorFromName(#ffccff) End If End If End Sub

需要對生成的 HTML 有更多的控制時過多地使用了 Datagrid(Repeater 也許是更好的選擇)

  如果懶散的程序員喜歡 Datagrid 控件(因為 Datagrid 控件為他們完成了很多工作)那麼有著極強控制欲的程序員必定喜歡 Repeater 控件如果需要或希望完全控制創建的所有 HTML請使用 Repeater 控件它能幫助您完成該任務Repeater 控件在性能上也略占優勢因為它不像 Datagrid 控件的所有內置功能那樣占用系統資源也可以考慮使用折衷的 DataList 控件它具備編輯和排序功能同時還具有在一行內重復顯示記錄的功能


From:http://tw.wingwit.com/Article/program/net/201311/13697.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.