在使用 DynamicField / DynamicControl 時,經常在PostBack時,會出現一個例外:
The DynamicControl/DynamicField needs to exist inside a data control that is bound to a data source that supports Dynamic Data.
中文為:
綁定到支持動態數據的數據源的數據控件內必須存在 DynamicControl/DynamicField
具體發生原因暫時不太清楚,估計是PostBack的事件流程和頁面正常加載不一致。當PostBack後,數據控件(如DetailsView, GridView, ListView 等)在狀態加載時, 會把所有的 Fileds或Columns初始化一次,而這一次,由於數據源沒有綁定,所以找不到相關的 MetaTable。在這種情況下,DynamicControl 和 DynamicField 都是丟出上述的例外。
不過,從應用上來看,如果數據綁定做的合理的話(比如在InitComplete以前綁定),是不會出現這個問題的。但是一旦出了這個問題,解決起來就比較麻煩了,因為常常有些人習慣於在Load中綁定數據,要修改的話,常常會牽連一大堆的代碼。希望對這個問題比較了解的朋友多多指教。
目前我采用的方法,可以不改變原有的綁定流程,可以跟以前的Eval、Bind等一樣使用,可以讓大家試試。在使用中如有發現有Bug,請發郵件告訴我。因為我最近幾個月都在應用 DynamicFieldTemplates 來開發應用程序,對這些問題比較關心。
使用這種方法,可以讓一些程序經驗不足的人,也能避開這個錯誤。
我分別從DynamicControl 和 DynamicField 繼承了新的類 DdControl 和 DdField,然後在初始化時,判斷是否存在MetaTable,如果不存在,則不再初始化。然後,程序中原本所有采用 DynamicControl/DynamicField的地方,都換成DdControl/DdField。
DdControl/DdField的源碼如下:
namespace Common { public class DdField : DynamicField { public override void InitializeCell(System.Web.UI.WebControls.DataControlFieldCell cell, System.Web.UI.WebControls.DataControlCellType cellType, System.Web.UI.WebControls.DataControlRowState rowState, int rowIndex) { // HACK: Fix bug for: The DynamicControl/DynamicField needs to exist inside a data control that is bound to a data source that supports Dynamic Data. if (base.Control.FindMetaTable() == null) return; base.InitializeCell(cell, cellType, rowState, rowIndex); } } } namespace Common { public class DdControl : DynamicControl { protected override void OnInit(EventArgs e) { // HACK: Fix bug for: The DynamicControl/DynamicField needs to exist inside a data control that is bound to a data source that supports Dynamic Data. if (this.FindMetaTable() != null) base.OnInit(e); } } }
使用時,只要在web.config中配置好前綴,就可以直接使用了。如:
<!-- 假設上述的程序生成 Common.dll --> <add tagPrefix="asp" namespace="Common" assembly="Common"/> <DetailsView > <Fields> <asp:DdField DataField="Name" /> </Fields> </DetailsView>