334
技術社區[雲棲]
ASP.Net開發者常見Datagrid錯誤
摘要:學習如何避免在使用ASP.NETDatagrid控件進行開發時可能發生的一些常見錯誤。Datagrid控件是Microsoft®ASP.NET中功能最強、用途最廣的Web控件之一,這一點已經得到了ASP.NET權威人士的認同。雖然Datagrid控件易於使用,但同樣易於給使用者帶來麻煩。以下是許多人所犯的一些錯誤,這些人包括從初學者到富有經驗的.NET專家。您可以看到許多苦悶的使用者在ASP.NET新聞組和論壇就這些錯誤提出問題。遵循本文概述的相當簡單的步驟,可以幫助您避免這些錯誤,並節約大量的開發時間。
可以使用Datagrid創建列表數據而沒有使用
我知道您不會再使用如下所示的代碼,但ASP.NET領域中許多守舊的用戶仍在繼續使用它們:

可以對以上代碼進行簡化,使其僅為:
<asp:datagridrunat="server"datasource="MyDataReader"/>,並調用.DataBind()方法。即使需要對HTML輸出進行特殊的控製,您也可以在用戶界麵上記錄集的內容重複出現的情況下,使用某個數據Web控件。
忘記在Page_Load事件中檢查IsPostBack
最常見的錯誤之一是忘記在數據綁定之前檢查頁麵的IsPostBack條件。例如,Datagrid處於“Edit”(編輯)模式時,忽略該項檢查將導致已編輯的值被數據源中的原始值覆蓋。
以下是包含IsPostBack檢查的一個典型Page_Load事件。BindGrid()是一個例程,用於導入並設置Datagrid的數據源,並調用DataBind()方法。

需要更大的靈活性時,仍堅持使用自動生成的列
如果Datagrid所處的環境需要任何一種特殊格式,或是需要使用Datagrid中的其他任何Web控件,那麼必須關閉AutoGenerateColumns。將AutoGenerateColumns屬性的設置保持為“True”(默認設置)的做法,僅在最簡單的Datagrid方案中有效。但對幾乎所有實際的應用程序,必須將該屬性設置為“False”,並在Datagrid聲明的<columns></columns>段中明確地指定列。MicrosoftVisualStudio®.NET用戶可以使用屬性生成器以圖形化的方式創建這些列。
注意:如果將AutoGenerateColumns的設置保持為“True”,並且在Datagrid的<columns>段中指定了列,那麼最終將得到對列的重複設置。係統將首先顯示特別聲明的列,隨後是所有自動生成的列。
嚐試僅使用控件ID來引用Datagrid項目中的控件
許多人沒有認識到,對於Datagrid的TemplateColumn下的ItemTemplate中的控件(例如帶有“MyTextBox”ID的TextBox控件),不能在後麵的代碼或是在ASPX頁麵的<script>段中用如下所示的代碼來直接調用該控件:

該代碼將導致可怕的“名稱‘MyTextBox’沒有聲明”錯誤。
因為Datagrid是由多個行(項目)組成的,所以數據源中的每一行實際都會有一個單獨的“MyTextBox”實例。ASP.NET在每個控件的ID前麵加上該控件層次結構中每個命名容器的ID,這樣Textbox將具有唯一的ID,與頁麵中所有其他控件的ID都不相同。例如,如果MyTextBox處於DataGrid1中,那麼生成的ID將是DataGrid1:_ctl2:MyTextBox。“_ctl2”代表MyTextBox所處的當前行。頁麵中其他MyTextBox實例的ID可能是DataGrid1:_ctl3:MyTextBox、DataGrid1:_ctl4:MyTextBox等等。要檢索需要查找的“MyTextBox”值,需要對適當的DataGridItem調用FindControl方法。該DataGridItem用作TextBox的父命名容器。
HTML

代碼

對FindControl調用的結果調用CType,將會把返回值由Object類型強製轉換成TextBox類型,以訪問.Text屬性。
可以(或應該)使用分頁而沒有使用
用戶未必希望在單個頁麵上滾動查看成千上萬條記錄。請確保您的應用程序設計合理,能夠處理可能會返回大量記錄的情況。
忘記在每個Datagrid事件中執行.DataBind()調用,從而導致回發
一個常見的問題是:“當我點擊Datagrid某一行中的Edit(編輯)鏈接時,頁麵回發,且不包含任何數據。這是什麼錯誤?”問題在於數據僅在頁麵第一次被調用時綁定到網格。在每個Datagrid事件(Edit、Update、Cancel、Page或Sort)中,請確保設置了Datagrid的Datasource屬性(除非已經在<asp:Datagrid>聲明中通過聲明的方式進行了設置),並對Datagrid調用了DataBind()方法。
運行時不必要地在Datagrid中動態創建Datagrid控件或列
在某些業務和技術方案中,在運行時創建ASP.NET控件是必要的,也是完全合適的。例如,有時需要在選擇其他頁麵選項後,才能在運行時確定用戶界麵。或是要創建一個複合服務器控件,其中的每個子控件都需要動態創建,因為無法以聲明的方式創建這些子控件。如果遇到這些情況,請注意,提交頁麵時不要保留這些動態控件。必須在頁麵生命周期的早期,在每次回發時重新創建動態控件(例如在Page_Init事件中)。警言:創建控件要早,創建控件要勤。
然而,如果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就夠了(請參閱示例代碼)。
表1:Datagrid事件與ViewState的依賴關係

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

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

需要對生成的HTML有更多的控製時,過多地使用了Datagrid(Repeater也許是更好的選擇)
如果懶散的程序員喜歡Datagrid控件(因為Datagrid控件為他們完成了很多工作),那麼有著極強控製欲的程序員必定喜歡Repeater控件。如果需要或希望完全控製創建的所有HTML,請使用Repeater控件,它能幫助您完成該任務。Repeater控件在性能上也略占優勢,因為它不像Datagrid控件的所有內置功能那樣占用係統資源。也可以考慮使用折衷的DataList控件,它具備編輯和排序功能,同時還具有在一行內重複顯示記錄的功能。
最後更新:2017-04-02 00:06:32