VS2010中呈現(xiàn)控件時(shí)出錯(cuò)的解決方法
在制作控件的時(shí)候容易遇到“呈現(xiàn)控件時(shí)出錯(cuò)”“發(fā)生了未處理的異常。未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例?!边@樣的錯(cuò)誤,如下圖:(也有可能僅僅只是因?yàn)槲丛O(shè)置runat="server"標(biāo)簽而導(dǎo)致該錯(cuò)誤,請(qǐng)先檢查該項(xiàng)。)
但是在編譯時(shí)/運(yùn)行時(shí)也都是沒(méi)有錯(cuò)誤的。
分析
如圖所示的情況我們稱(chēng)之為“設(shè)計(jì)時(shí)”以區(qū)別于“編譯時(shí)”/“運(yùn)行時(shí)”。
設(shè)計(jì)時(shí):在ASP.NET環(huán)境中也就是當(dāng)我們?cè)赩isual Studio中使用網(wǎng)頁(yè)設(shè)計(jì)器進(jìn)行編輯的時(shí)候。直接的理解就是在ASPX頁(yè)面切換到“設(shè)計(jì)”的時(shí)候。
編譯時(shí):直接的理解就是當(dāng)你進(jìn)行編譯的時(shí)候,通常這個(gè)時(shí)候的錯(cuò)誤是由類(lèi)型檢查,參數(shù)匹配等顯式可直接通過(guò)語(yǔ)法約束所限制的錯(cuò)誤。
運(yùn)行時(shí):直接的理解就是當(dāng)你進(jìn)行預(yù)覽/運(yùn)行的時(shí)候。通常這個(gè)時(shí)候的錯(cuò)誤則是由具體的異常,邏輯錯(cuò)誤所組成的。
讓我們分析控件在設(shè)計(jì)時(shí)的表現(xiàn),我們的控件在設(shè)計(jì)時(shí)的時(shí)候,VS智能地模擬輸出控件在運(yùn)行時(shí)的樣貌,控件的呈現(xiàn)通過(guò)了一定順序的方法,并最終形成了當(dāng)前輸出。按照標(biāo)準(zhǔn),我們應(yīng)該是在Render或RenderContents中對(duì)控件進(jìn)行了輸出的操作(事實(shí)上其他也是可以,但我們通常也不那么做,或者說(shuō)更多的“呈現(xiàn)控件時(shí)出錯(cuò)”的異常主要來(lái)自于Render或RenderContents)。
從錯(cuò)誤的提示“未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例。”從這一句話來(lái)看,也就是說(shuō),有一個(gè)或者以上的對(duì)象的實(shí)例在沒(méi)有賦初值的情況下就被使用了。
讓我們窺視一下我們的代碼:
protected override void RenderContents(HtmlTextWriter writer) { UpButton.Text = Page.Server.HtmlDecode(UpButton.Text); DownButton.Text = Page.Server.HtmlDecode(DownButton.Text); base.RenderContents(writer); }
因?yàn)樵摽丶谠O(shè)計(jì)的時(shí)候需要有一個(gè)向上的按鈕和一個(gè)向下的按鈕,分別需要用兩個(gè)特殊的標(biāo)點(diǎn)符號(hào)向上和向下,而這兩個(gè)符號(hào)需要通過(guò)設(shè)置如下所示的代碼編號(hào)才可以正確地被瀏覽器呈現(xiàn):
private string upButtonText = "∧"; private string downButtonText = "∨";
而這兩個(gè)符號(hào)在呈現(xiàn)前卻會(huì)被頁(yè)面進(jìn)行一個(gè)HtmlEncode方法編譯后再輸出,而這兩個(gè)特殊的標(biāo)志卻只能通過(guò)直接輸出的方式進(jìn)行呈現(xiàn),也就是說(shuō)在HtmlEncode之后只能將該特殊標(biāo)志以文本的形式輸出∧ ∨而不會(huì)輸出向上和向下的箭頭。這時(shí)候我們需要引入它的反向方法Page.Server.HtmlDecode進(jìn)行解碼,注意到這里我們使用了Page實(shí)例,該實(shí)例只有在頁(yè)面真實(shí)存在的情況下才為非空,否則后續(xù)的操作將是對(duì)null的操作,而這樣的操作將會(huì)顯示“未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例?!边@樣的錯(cuò)誤。
設(shè)計(jì)時(shí):我們剛才提到了,設(shè)計(jì)時(shí)僅僅只是模擬頁(yè)面呈現(xiàn)的過(guò)程,而頁(yè)面事實(shí)上是不存在的。因此在這個(gè)時(shí)候Page對(duì)象的實(shí)例將為空,后續(xù)的調(diào)用將引發(fā)異常。
假設(shè)說(shuō)我們只有這個(gè)方法用于處理當(dāng)前所需要的行為,那么我們?cè)谡{(diào)用Page的時(shí)候必將導(dǎo)致null的對(duì)象并致使后續(xù)操作發(fā)生異常。這個(gè)時(shí)候我們引入“設(shè)計(jì)模式”這個(gè)概念(非DesignPattern而是DesignMode),DesignMode是由Control類(lèi)的一個(gè)受保護(hù)的(protected)屬性,它獲取一個(gè)值,用以指示該組件當(dāng)前是否處于設(shè)計(jì)模式。這里的設(shè)計(jì)模式也就相當(dāng)于設(shè)計(jì)時(shí)的概念。
因此我們可以將代碼改造為如下形式:
protected override void RenderContents(HtmlTextWriter writer) { if (!DesignMode) { UpButton.Text = Page.Server.HtmlDecode(UpButton.Text); DownButton.Text = Page.Server.HtmlDecode(DownButton.Text); } base.RenderContents(writer); }
這樣只有在非設(shè)計(jì)時(shí)的時(shí)候,我們才引入Page對(duì)象的實(shí)例,因此設(shè)計(jì)時(shí)的異常將迎刃而解。
總結(jié)
因此在設(shè)計(jì)控件的時(shí)候,特別是在考慮控件呈現(xiàn)的時(shí)候,為了避免類(lèi)似異常的發(fā)生,我們應(yīng)該考慮該控件在設(shè)計(jì)時(shí)能夠獲取足夠的資源,對(duì)于未能獲取資源的項(xiàng),我們應(yīng)該顯式將其區(qū)分(如上代碼中使用DesignMode來(lái)判斷是否為設(shè)計(jì)時(shí)要執(zhí)行的代碼)。
擴(kuò)展
剛才我們所見(jiàn)到的情形可以歸結(jié)為在設(shè)計(jì)時(shí)無(wú)法引用具體實(shí)例所導(dǎo)致的異常,類(lèi)似該異常的還會(huì)有數(shù)據(jù)庫(kù)/文件系統(tǒng)讀取、變量未附初值、調(diào)用了類(lèi)似Page的屬性如Session,Page.Request.QueryString等。在頁(yè)面設(shè)計(jì)的時(shí)候由于以上部分方案特別是調(diào)用到Page的相關(guān)方法的由于頁(yè)面總是會(huì)存在,因此我們不會(huì)經(jīng)??吹剿鼈兂霎惓#谠O(shè)計(jì)控件的時(shí)候我們更應(yīng)該注意。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- VS2010/MFC編程(常用控件:樹(shù)形控件Tree Control控件創(chuàng)建h和實(shí)例)
- 使用VS2010 C#開(kāi)發(fā)ActiveX控件(下),完整代碼打包下載
- 使用VS2010 C#開(kāi)發(fā)ActiveX控件(上)
- asp.net GridView控件中模板列CheckBox全選、反選、取消
- asp.net 打印控件使用方法
- asp.net+jquery滾動(dòng)滾動(dòng)條加載數(shù)據(jù)的下拉控件
- Asp.net 菜單控件簡(jiǎn)潔版
- asp.net AjaxControlToolKit--TabContainer控件的介紹
- ASP.NET單選按鈕控件RadioButton常用屬性和方法介紹
- asp.net fileupload控件上傳文件與多文件上傳
相關(guān)文章
Entity Framework使用Code First模式管理存儲(chǔ)過(guò)程
本文詳細(xì)講解了Entity Framework使用Code First模式管理存儲(chǔ)過(guò)程的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03asp.net 服務(wù)器控件的 ID,ClientID,UniqueID 的區(qū)別
asp.net 服務(wù)器控件的 ID,ClientID,UniqueID 的區(qū)別分析,需要的朋友可以參考下。2010-04-04Entity Framework使用Code First模式管理數(shù)據(jù)庫(kù)
本文詳細(xì)講解了Entity Framework使用Code First模式管理數(shù)據(jù)庫(kù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03asp.net下生成英文字符數(shù)字驗(yàn)證碼的代碼
用了asp.net隨機(jī)數(shù),獲取指定位數(shù)的字母或數(shù)字以后,進(jìn)行圖片輸出的驗(yàn)證碼函數(shù)。2009-12-12Asp.net mvc 數(shù)據(jù)調(diào)用示例代碼
Asp.net mvc 數(shù)據(jù)調(diào)用示例代碼,學(xué)習(xí)asp.net mvc框架的朋友可以參考下。2010-10-10Asp.net Socket客戶(hù)端(遠(yuǎn)程發(fā)送和接收數(shù)據(jù))
通過(guò)Socket遠(yuǎn)程發(fā)送與接收數(shù)據(jù)的代碼類(lèi)2008-11-11.NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)查詢(xún)排序
這篇文章主要介紹了如何通過(guò).NET 6實(shí)現(xiàn)查詢(xún)排序功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí).NET 6有一定的幫助,感興趣的同學(xué)可以了解一下2022-01-01asp.net 模擬提交有文件上傳的表單(通過(guò)http模擬上傳文件)
通過(guò)HTTP模擬GET或POST請(qǐng)求,提交數(shù)據(jù)到服務(wù)端獲取響應(yīng),比較常見(jiàn)些;但如上傳文件到服務(wù)端,使用html form當(dāng)然簡(jiǎn)單了,而因環(huán)境所限有時(shí)需要使用模擬方法去提交有附件(文件上傳)的表單。2010-02-02如何解決asp.net負(fù)載均衡時(shí)Session共享的問(wèn)題
這篇文章主要介紹了解決asp.net負(fù)載均衡時(shí)Session共享的問(wèn)題,詳細(xì)的介紹了ASP.Net session存儲(chǔ)方式以及如何實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11.Net Core中自定義認(rèn)證實(shí)現(xiàn)
本文主要介紹了.Net Core中自定義認(rèn)證實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01