国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

常見Datagrid錯誤

2024-07-21 02:22:04
字體:
供稿:網(wǎng)友
中國最大的web開發(fā)資源網(wǎng)站及技術(shù)社區(qū),


摘要:學(xué)習(xí)如何避免在使用 asp.net datagrid 控件進(jìn)行開發(fā)時可能發(fā)生的一些常見錯誤(本文包含一些指向英文站點的鏈接)。

datagrid 控件是 microsoft® asp.net 中功能最強(qiáng)、用途最廣的 web 控件之一,這一點已經(jīng)得到了 asp.net 權(quán)威人士的認(rèn)同。雖然 datagrid 控件易于使用,但同樣易于給使用者帶來麻煩。以下是許多人所犯的一些錯誤,這些人包括從初學(xué)者到富有經(jīng)驗的 .net 專家。您可以看到許多苦悶的使用者在 asp.net 新聞組和論壇就這些錯誤提出問題。遵循本文概述的相當(dāng)簡單的步驟,可以幫助您避免這些錯誤,并節(jié)約大量的開發(fā)時間。

可以使用 datagrid 創(chuàng)建列表數(shù)據(jù)而沒有使用
我知道您不會再使用如下所示的代碼,但 asp.net 領(lǐng)域中許多守舊的用戶仍在繼續(xù)使用它們:

response.write("<table>")
while mydatareader.read()
response.write("<tr>")
response.write("<td>")
response.write(mydatareader(0))
response.write("</td>")
response.write("</tr>")
loop
response.write("</table>")
可以對以上代碼進(jìn)行簡化,使其僅為:

<asp:datagrid runat="server" datasource="mydatareader"/>,并調(diào)用 .databind() 方法。即使需要對 html 輸出進(jìn)行特殊的控制,您也可以在用戶界面上記錄集的內(nèi)容重復(fù)出現(xiàn)的情況下,使用某個數(shù)據(jù) web 控件。

忘記在 page_load 事件中檢查 ispostback
最常見的錯誤之一是忘記在數(shù)據(jù)綁定之前檢查頁面的 ispostback 條件。例如,datagrid 處于“edit”(編輯)模式時,忽略該項檢查將導(dǎo)致已編輯的值被數(shù)據(jù)源中的原始值覆蓋。然而,該規(guī)則至少有一個主要的例外,請參閱持續(xù)使用大型 viewstate。

以下是包含 ispostback 檢查的一個典型 page_load 事件。bindgrid() 是一個例程,用于導(dǎo)入并設(shè)置 datagrid 的數(shù)據(jù)源,并調(diào)用 databind() 方法。

sub page_load
if not ispostback then
bindgrid()
end if
end sub
需要更大的靈活性時,仍堅持使用自動生成的列
如果 datagrid 所處的環(huán)境需要任何一種特殊格式,或是需要使用 datagrid 中的其他任何 web 控件,那么必須關(guān)閉 autogeneratecolumns。將 autogeneratecolumns 屬性的設(shè)置保持為“true”(默認(rèn)設(shè)置)的做法,僅在最簡單的 datagrid 方案中有效。但對幾乎所有實際的應(yīng)用程序,必須將該屬性設(shè)置為“false”,并在 datagrid 聲明的 <columns></columns> 段中明確地指定列。microsoft visual studio&reg; .net 用戶可以使用屬性生成器以圖形化的方式創(chuàng)建這些列。

注意:如果將 autogeneratecolumns 的設(shè)置保持為“true”,并且在 datagrid 的 <columns> 段中指定了列,那么最終將得到對列的重復(fù)設(shè)置。系統(tǒng)將首先顯示特別聲明的列,隨后是所有自動生成的列。
嘗試僅使用控件 id 來引用 datagrid 項目中的控件
許多人沒有認(rèn)識到,對于 datagrid 的 templatecolumn 下的 itemtemplate 中的控件(例如帶有“mytextbox”id 的 textbox 控件),不能在后面的代碼或是在 aspx 頁面的 <script> 段中用如下所示的代碼來直接調(diào)用該控件:

dim myvalue as string = mytextbox.text
該代碼將導(dǎo)致可怕的“名稱‘mytextbox’沒有聲明”錯誤。

因為 datagrid 是由多個行(項目)組成的,所以數(shù)據(jù)源中的每一行實際都會有一個單獨的“mytextbox”實例。asp.net 在每個控件的 id 前面加上該控件層次結(jié)構(gòu)中每個命名容器的 id,這樣 textbox 將具有唯一的 id,與頁面中所有其他控件的 id 都不相同。例如,如果 mytextbox 處于 datagrid1 中,那么生成的 id 將是 datagrid1:_ctl2:mytextbox。“_ctl2”代表 mytextbox 所處的當(dāng)前行。頁面中其他 mytextbox 實例的 id 可能是 datagrid1:_ctl3:mytextbox、datagrid1:_ctl4:mytextbox 等等。要檢索需要查找的“mytextbox”值,需要對適當(dāng)?shù)?datagriditem 調(diào)用 findcontrol 方法。該 datagriditem 用作 textbox 的父命名容器。

html:

<asp:datagrid runat="server" id="datagrid1">
<columns>
<asp:templatecolumn>
<itemtemplate>
<asp:textbox runat="server" id="mytextbox"/>
</itemtemplate>
</asp:templatecolumn>
</columns>
代碼:

sub datagrid1_updatecommand(sender as object, _
e as datagridcommandeventargs)
dim myvalue as string = _
ctype(e.item.findcontrol("mytextbox"), textbox).text
'對 myvalue 執(zhí)行操作
end sub
對 findcontrol 調(diào)用的結(jié)果調(diào)用 ctype,將會把返回值由 object 類型強(qiáng)制轉(zhuǎn)換成 textbox 類型,以訪問 .text 屬性。

可以(或應(yīng)該)使用分頁而沒有使用
用戶未必希望在單個頁面上滾動查看成千上萬條記錄。請確保您的應(yīng)用程序設(shè)計合理,能夠處理可能會返回大量記錄的情況。有關(guān)如何在 datagrid 中實現(xiàn)分頁的信息,請參閱 paging in datagrid quickstart tutorial。在 scott mitchell 的文章 creating a pageable, sortable datagrid 中可以找到更多的信息。

忘記在每個 datagrid 事件中執(zhí)行 .databind() 調(diào)用,從而導(dǎo)致回發(fā)
一個常見的問題是:“當(dāng)我點擊 datagrid 某一行中的 edit(編輯)鏈接時,頁面回發(fā),且不包含任何數(shù)據(jù)。這是什么錯誤?”問題在于數(shù)據(jù)僅在頁面第一次被調(diào)用時綁定到網(wǎng)格。在每個 datagrid 事件(edit、update、cancel、page 或 sort)中,請確保設(shè)置了 datagrid 的 datasource 屬性(除非已經(jīng)在 <asp:datagrid> 聲明中通過聲明的方式進(jìn)行了設(shè)置),并對 datagrid 調(diào)用了 databind() 方法。

運行時不必要地在 datagrid 中動態(tài)創(chuàng)建 datagrid 控件或列
在某些業(yè)務(wù)和技術(shù)方案中,在運行時創(chuàng)建 asp.net 控件是必要的,也是完全合適的。例如,有時需要在選擇其他頁面選項后,才能在運行時確定用戶界面。或是要創(chuàng)建一個復(fù)合服務(wù)器控件,其中的每個子控件都需要動態(tài)創(chuàng)建,因為無法以聲明的方式創(chuàng)建這些子控件。如果遇到這些情況,請注意,提交頁面時不要保留這些動態(tài)控件。必須在頁面生命周期的早期,在每次回發(fā)時重新創(chuàng)建動態(tài)控件(例如在 page_init 事件中)。警言:創(chuàng)建控件要早,創(chuàng)建控件要勤。有關(guān)如何動態(tài)創(chuàng)建控件的詳細(xì)信息,請參閱 microsoft knowledge base 文章 how to:dynamically create controls in asp.net with visual basic .net。

然而,如果 datagrid 應(yīng)用程序中不是一定需要動態(tài)創(chuàng)建控件,請避免使用該技術(shù),以免遇到麻煩。盡管可能創(chuàng)建動態(tài) datagrid,但它們會引發(fā)各種事件,這通常都會令人頭疼。換句話說,不要動態(tài)創(chuàng)建控件,以避免因為創(chuàng)建控件使 aspx 文件變得散亂。

持續(xù)使用大型 viewstate
datagrid 控件會在頁面中添加大量的 viewstate,這一點令人討厭,因為這會導(dǎo)致呈現(xiàn)給用戶的頁面的總體大小急劇增加。要使頁面大小不增加,最簡單的方法是無論對整個頁面,還是單獨對某些特定的控件,都禁用 viewstate。例如,如果頁面不產(chǎn)生回發(fā),那么對整個頁面禁用 viewstate 是安全的。否則,請對兩次回發(fā)之間狀態(tài)信息不會發(fā)生更改的各個控件禁用 viewstate,或者對不需要隱藏字段來跟蹤自身狀態(tài)的那些控件禁用 viewstate。

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

表 1:datagrid 事件與 viewstate 的依賴關(guān)系

事件 是否依賴于 viewstate? 要存儲在 viewstate 中的字段
itemcreated 無
itemdatabound 無
sortcommand 是 sortexpression
editcommand 是 edititemindex
pageindexchanged 是 currentpageindex
selectedindexchanged 無

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

sub page_load
if not viewstate("edititemindex") is nothing then
datagrid1.edititemindex = viewstate("edititemindex")
end if
if not viewstate("currentpageindex") is nothing then
datagrid1.currentpageindex = viewstate("currentpageindex")
end if
bindgrid()
end sub

sub bindgrid()
dim dv as dataview
dv = getdatasource()
dv.sort = viewstate("sortexpression")
datagrid1.datasource = dv
datagrid1.databind()
end sub

sub datagrid1_sortcommand(s as object, _
e as datagridsortcommandeventargs)
viewstate("sortexpression") = e.sortexpression
bindgrid()
end sub

sub datagrid1_editcommand(s as object, _
e as datagridcommandeventargs)
datagrid1.edititemindex = e.item.itemindex
viewstate("edititemindex") = e.item.itemindex
bindgrid()
end sub

sub datagrid1_pageindexchanged(s as object, _
e as datagridpagechangedeventargs)
datagrid1.currentpageindex = e.newpageindex
viewstate("currentpageindex") = e.newpageindex
bindgrid()
end sub

使用 itemdatabound 或 itemcreated 事件時,忘記檢查適當(dāng)?shù)?listitemtype
datagrid 控件對每個數(shù)據(jù)行引發(fā)兩個事件。首次將每行添加到 datagrid 時將引發(fā) itemcreated 事件,將數(shù)據(jù)綁定到每行時將引發(fā) itemdatabound 事件。添加單元格到 datagrid 的表格輸出時,這些事件可以用于控制每個單元格的外觀或內(nèi)容。例如,可以基于數(shù)值的范圍修改單元格的背景顏色。但關(guān)鍵是要記住,這些事件的引發(fā)針對的是所有 datagrid 項目類型,包括頁眉、頁腳和分頁程序項目。如果執(zhí)行 itemdatabound 事件期間,沒有在引用項目的數(shù)據(jù)之前仔細(xì)檢查項目類型,第一個項目(通常是標(biāo)題行)就將發(fā)生錯誤。如果 datagrid 啟用了分頁,且將其設(shè)置為在頂端顯示,那么第一個項目就會成為分頁程序項目。以下示例代碼顯示如何在引用項目數(shù)據(jù)之前進(jìn)行正確的 listitemtype 檢查。不要忘了 alternatingitem!

sub datagrid1_itemdatabound(source as object, _
e as datagriditemeventargs)
if (e.item.itemtype = listitemtype.item or _
e.item.itemtype = listitemtype.alternatingitem) then
if e.item.dataitem("forumdate") < datetime.today then
e.item.cells(1).backcolor =
system.drawing.color.fromname("#ffccff")
end if
end if
end sub

需要對生成的 html 有更多的控制時,過多地使用了 datagrid(repeater 也許是更好的選擇)
如果懶散的程序員喜歡 datagrid 控件(因為 datagrid 控件為他們完成了很多工作),那么有著極強(qiáng)控制欲的程序員必定喜歡 repeater 控件。如果需要或希望完全控制創(chuàng)建的所有 html,請使用 repeater 控件,它能幫助您完成該任務(wù)。repeater 控件在性能上也略占優(yōu)勢,因為它不像 datagrid 控件的所有內(nèi)置功能那樣占用系統(tǒng)資源。也可以考慮使用折衷的 datalist 控件,它具備編輯和排序功能,同時還具有在一行內(nèi)重復(fù)顯示記錄的功能。

參考資料
dotnetjohn 網(wǎng)站上的 viewstate
datagrid quickstart tutorials
有關(guān) datagrid web 服務(wù)器控件的重要問題
creating a pageable, sortable datagrid


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 定兴县| 宁晋县| 上蔡县| 巴中市| 龙井市| 旬邑县| 光泽县| 同心县| 静宁县| 永嘉县| 孙吴县| 遂溪县| 福建省| 茌平县| 洪湖市| 平潭县| 迭部县| 江川县| 罗田县| 青阳县| 阿尔山市| 额济纳旗| 阳城县| 百色市| 崇礼县| 长葛市| 山丹县| 山阳县| 勃利县| 揭东县| 营山县| 中西区| 曲阳县| 普格县| 织金县| 通河县| 罗江县| 沧州市| 牙克石市| 宁南县| 盐津县|