asp.net控件开发基础(21)
生活随笔
收集整理的這篇文章主要介紹了
asp.net控件开发基础(21)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
示例代碼
?????? 上篇介紹了在asp.net2.0版本下面如何簡單的定義數據綁定控件。雖然DataBoundControl為我們提供了便利,我們以后可以從此類開始編寫數據綁定控件。但是在2.0版本未到來之前,你已經為自己訂制了一些數據綁定控件,既然2.0版本已經提供了數據源控件,你是否有想法,讓你原有的控件也升級到同時支持通過設置DataSource屬性和數據源控件來獲取數據源,這樣以后我們就可以省省工作了。這次我們就來討論這個話題,讓舊版本的數據綁定控件支持數據源控件。
一.準備升級數據綁定控件
即使asp.net1.1版本的一些控件也都已經支持數據源控件了,如Repeater,BaseDataList等.但本身這些對象并不是從BaseDataBoundControl和DataBoundControl等類繼承下來的,如Repeater其是從Control下繼承的一個模板控件,其并不需要這么多從WebControl繼承下來的屬性,如果你想讓它支持數據源控件,你首先會想到改變控件基類,從DataBoundControl開始,這是一個好想法,但可能有些情況下并不允許這么做。上次說到了BaseDataList和DataBoundControl,BaseDataList也支持數據源控件了,所以我認為從此類繼承是完全沒有問題的。另外的做法就是在不改變原有控件基類的情況下,你還是需要老老實實給原控件添加一些代碼支持數據源控件。那么就開始吧.
二.具體實現
本次例子跟上篇相同,相同地方就略過了
1.定義基本成員
整個控件的實現方式跟DataBoundControl實現方式很相似,我們可以看看MSDN中,BaseDataList等基類添加了哪些元素,然后模仿著實現.如果對BaseDataBoundControl和DataBoundControl這兩個類成員了解的話,你將對下面成員屬性很熟悉,添加這些基本成員
(1)
???????/**////?<summary>
????????///?該值指示控件是否已經初始化
????????///?</summary>
????????protected?bool?Initialized
????????{
????????????get
????????????{
????????????????return?initialized;
????????????}
????????}
???????public?string?DataMember
???????{
???????????get
???????????{
???????????????object?member?=?ViewState["DataMember"];
???????????????if?(member?==?null)
???????????????????return?string.Empty;
???????????????else
???????????????????return?(string)member;
???????????}
???????????set
???????????{
???????????????ViewState["DataMember"]?=?value;
???????????????this.OnDataPropertyChanged();
???????????}
???????}
????????/**////?<summary>
????????///?為數據綁定控件提供數據源
????????///?</summary>
???????public?IEnumerable?DataSource
???????{
???????????get
???????????{
???????????????return?dataSource;
???????????}
???????????set
???????????{
???????????????if?((value?is?IEnumerable)?||?(value?is?IListSource)?||?(value?==?null))
???????????????????dataSource?=?value;
???????????????else
???????????????????throw?new?Exception("錯誤的數據源類型");
???????????????OnDataPropertyChanged();
???????????}
???????}
????????/**////?<summary>
????????///?數據源控件的?ID?屬性
????????///?</summary>
????????[DefaultValue(""),?IDReferenceProperty(typeof(DataSourceControl))]
????????public?virtual?string?DataSourceID
????????{
????????????get
????????????{
????????????????object?dataSourceID?=?ViewState["DataSourceID"];
????????????????if?(dataSourceID?!=?null)
????????????????{
????????????????????return?(string)dataSourceID;
????????????????}
????????????????return?string.Empty;
????????????}
????????????set
????????????{
????????????????this.ViewState["DataSourceID"]?=?value;
????????????????this.OnDataPropertyChanged();
????????????}
????????}
????????/**////?<summary>
????????///?獲取是否設置?DataSourceID?屬性的值
????????///?</summary>
????????protected?bool?IsBoundUsingDataSourceID
????????{
????????????get
????????????{
????????????????return?(DataSourceID.Length?>?0);
????????????}
????????}
????????/**////?<summary>
????????///?是否需要綁定到其指定的數據源
????????///?</summary>
????????protected?bool?RequiresDataBinding
????????{
????????????get
????????????{
????????????????return?requiresDataBinding;
????????????}
????????????set
????????????{
????????????????requiresDataBinding?=?value;
????????????}
????????}
????????/**////?<summary>
????????///?用于檢索數據的?DataSourceSelectArguments?對象。默認為?Empty?值
????????///?</summary>
????????protected?DataSourceSelectArguments?SelectArguments
????????{
????????????get
????????????{
????????????????if?(selectArguments?==?null)
????????????????{
????????????????????selectArguments?=?CreateDataSourceSelectArguments();
????????????????}
????????????????return?selectArguments;
????????????}
????????}
(2)上面幾個屬性涉及到幾個方法
???????/**////?<summary>
????????///?創建空的?DataSourceSelectArguments?對象
????????///?</summary>
????????///?<returns></returns>
????????protected?virtual?DataSourceSelectArguments?CreateDataSourceSelectArguments()
????????{
????????????return?DataSourceSelectArguments.Empty;
????????}
???????/**////?<summary>
???????///?如果設置了?DataSourceID?屬性且數據綁定控件標記為需要綁定,則調用?DataBind?方法
????????///?OnPreRender中調用
???????///?</summary>
???????protected?void?EnsureDataBound()
???????{
???????????if?(RequiresDataBinding?&&?(DataSourceID.Length?>?0))
???????????{
???????????????DataBind();
???????????}
???????}
???????
???????/**////?<summary>
???????///?在某一基數據源標識屬性更改后,將數據綁定控件重新綁定到其數據
???????///?</summary>
???????protected?virtual?void?OnDataPropertyChanged()
???????{
???????????if?(initialized)
???????????{
???????????????RequiresDataBinding?=?true;
???????????}
???????????currentViewValid?=?false;
???????}
上面的幾個屬性和方法可以一起來看看了,在更改數據源標識時都會調用OnDataPropertyChanged方法,然后到了EnsureDataBound方法(此方法在OnPreRender方法中調用)在使用數據源控件情況下自動調用DataBind方法。另外Initialized屬性會在控件初始化時設置.
2.獲取與數據綁定控件關聯的 接口
數據源控件實現了IDataSource接口,此接口定義了數據源最基本的元素,數據綁定控件要根據DataSourceID屬性從容器中獲取與其關聯的 接口。如下實現
?????//?從容器中獲取DataControl
???????private?Control?FindControl(Control?control,?string?controlID)
????????{
????????????Control?namingContainer?=?control;
????????????Control?dataControl?=?null;
????????????if?(control?!=?control.Page)
????????????{
????????????????while?((dataControl?==?null)?&&?(namingContainer?!=?control.Page))
????????????????{
????????????????????namingContainer?=?namingContainer.NamingContainer;
????????????????????if?(namingContainer?==?null)
????????????????????{
????????????????????????throw?new?HttpException("DataBoundControlHelper_NoNamingContainer");
????????????????????}
????????????????????dataControl?=?namingContainer.FindControl(controlID);
????????????????}
????????????????return?dataControl;
????????????}
????????????return?control.FindControl(controlID);
????????}
????????/**////?<summary>
????????///?檢索與數據綁定控件關聯的?IDataSource?接口
????????///?</summary>
????????///?<returns></returns>
???????protected?virtual?IDataSource?GetDataSource()
???????{
???????????if?(this.currentDataSource?!=?null)
???????????{
???????????????return?currentDataSource;
???????????}
???????????//獲取數據源控件
???????????IDataSource?source?=?null;
???????????string?controlID?=?DataSourceID;
???????????if?(controlID.Length?!=?0)
???????????{
???????????????Control?control?=?FindControl(this,?controlID);
???????????????source?=?control?as?IDataSource;
???????????}
???????????return?source;
???????}
3.獲取數據源視圖
第二步的實現是為此服務的
????????private?DataSourceView?ConnectToDataSourceView()
????????{
????????????if?(!currentViewValid?||?base.DesignMode)
????????????{
????????????????
????????????????if?((currentView?!=?null)?&&?currentViewIsFromDataSourceID)
????????????????{
????????????????????currentView.DataSourceViewChanged?-=?new?EventHandler(this.OnDataSourceViewChanged);
????????????????}
????????????????this.currentDataSource?=?GetDataSource();
????????????????//從DataSource獲取數據源
????????????????if?(this.currentDataSource?==?null)
????????????????{
????????????????????this.currentDataSource?=?new?ReadOnlyDataSource(DataSource,?DataMember);
????????????????}
????????????????DataSourceView?view?=?this.currentDataSource.GetView(DataMember);
????????????????currentViewIsFromDataSourceID?=?IsBoundUsingDataSourceID;
????????????????currentView?=?view;
????????????????
????????????????if?((currentView?!=?null)?&&?currentViewIsFromDataSourceID)
????????????????{
????????????????????currentView.DataSourceViewChanged?+=?new?EventHandler(this.OnDataSourceViewChanged);
????????????????}
????????????????currentViewValid?=?true;
????????????}
????????????return?currentView;
????????}
????????/**////?<summary>
????????///?獲取數據源視圖
????????///?</summary>
????????///?<returns></returns>
????????protected?virtual?DataSourceView?GetData()
????????{
??????????return?ConnectToDataSourceView();
????????}
請注意ConnectToDataSourceView方法,前后分別在移除和添加一個事件,將RequiresDataBinding屬性設置為true重新綁定,然后再看中間這段代碼
????????????????if?(this.currentDataSource?==?null)
????????????????{
????????????????????this.currentDataSource?=?new?ReadOnlyDataSource(DataSource,?DataMember);
????????????????}
即當未使用數據源控件時,則就從ReadOnlyDataSource對象通過設置DataSource和DataMember屬性來獲取IDataSource 接口,然后才能獲取到數據源視圖.下面為ReadOnlyDataSource和ReadOnlyDataSourceView的簡單實現,在此不做解釋.下次再來講這個東西
???public?class?ReadOnlyDataSource?:?IDataSource
????{
????????
????????private?string?_dataMember;
????????private?object?_dataSource;
????????private?static?string[]?ViewNames?=?new?string[0];
???????
????????event?EventHandler?IDataSource.DataSourceChanged
????????{
????????????add
????????????{
????????????}
????????????remove
????????????{
????????????}
????????}
????????
????????public?ReadOnlyDataSource(object?dataSource,?string?dataMember)
????????{
????????????this._dataSource?=?dataSource;
????????????this._dataMember?=?dataMember;
????????}
????????DataSourceView?IDataSource.GetView(string?viewName)
????????{
????????????IDataSource?source?=?_dataSource?as?IDataSource;
????????????if?(source?!=?null)
????????????{
????????????????return?source.GetView(viewName);
????????????}
????????????return?new?ReadOnlyDataSourceView(this,?this._dataMember,DataSourceHelper.ResolveDataSource(this._dataSource,?this._dataMember));
????????}
????????ICollection?IDataSource.GetViewNames()
????????{
????????????return?ViewNames;
????????}
????}
?public?class?ReadOnlyDataSourceView?:?DataSourceView
????{
????????private?IEnumerable?dataSource;
????????public?ReadOnlyDataSourceView(ReadOnlyDataSource?owner,?string?name,?IEnumerable?dataSource)
????????????:?base(owner,?name)
????????{
????????????this.dataSource=dataSource?;
????????}
????????protected?override?IEnumerable?ExecuteSelect(DataSourceSelectArguments?arguments)
????????{
????????????arguments.RaiseUnsupportedCapabilitiesError(this);
????????????return?dataSource;
????????}
????}
4.獲取數據
接著你便可以在DataBind方法中通過獲取到的數據源視圖異步獲取數據了,本來我們可以調用其ExecuteSelect方法的,可惜我們無法調用此方法,只好異步調用。接著的PerformDataBinding方法跟上篇實現一樣。不再列出
記得在DataBind方法將RequiresDataBinding?屬性設置為true
????????/**////?<summary>
????????///?將數據源綁定到控件
????????///?</summary>
????????public?override?void?DataBind()
????????{
????????????if?(!IsBoundUsingDataSourceID)
????????????{
????????????????OnDataBinding(EventArgs.Empty);
????????????}
????????????GetData().Select(CreateDataSourceSelectArguments(),
????????????????OnDataSourceViewSelectCallback);
????????????RequiresDataBinding?=?false;
????????????MarkAsDataBound();
????????}
????????private?void?OnDataSourceViewSelectCallback(IEnumerable?retrievedData)
????????{
????????????if?(IsBoundUsingDataSourceID)
????????????{
????????????????OnDataBinding(EventArgs.Empty);
????????????}
????????????PerformDataBinding(retrievedData);
????????}
5.重寫控件生命周期事件
其中在OnPreRender方法中調用了EnsureDataBound方法,其他方法的話可以發現在很多不同情況下將RequiresDataBinding和Initialized屬性設置為True.做了數據綁定的初始化工作。這里估計我也解釋不清楚,大家還是了解下控件的生命周期,了解其事件的使用,再理解吧.這里可以參考jessezhao的這篇翻譯
????????protected?override?void?OnInit(EventArgs?e)
????????{
????????????base.OnInit(e);
????????????if?(this.Page?!=?null)
????????????{
????????????????this.Page.PreLoad?+=?new?EventHandler(this.OnPagePreLoad);
????????????????if?(!base.IsViewStateEnabled?&&?this.Page.IsPostBack)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????}
????????}
????????private?void?OnPagePreLoad(object?sender,?EventArgs?e)
????????{
????????????initialized?=?true;
????????????if?(Page?!=?null)
????????????{
????????????????Page.PreLoad?-=?new?EventHandler(OnPagePreLoad);
????????????????if?(!Page.IsPostBack)
????????????????{
????????????????????RequiresDataBinding?=?true;
????????????????}
????????????????if?((Page.IsPostBack?&&?base.IsViewStateEnabled)?&&?(ViewState["DataBound"]?==?null))
????????????????{
????????????????????RequiresDataBinding?=?true;
????????????????}
????????????}
????????}
????????protected?override?void?OnPreRender(EventArgs?e)
????????{
????????????EnsureDataBound();
????????????base.OnPreRender(e);
????????}
????????protected?override?void?OnLoad(EventArgs?e)
????????{
????????????this.initialized?=?true;
????????????this.ConnectToDataSourceView();
????????????if?(this.Page?!=?null?&&?this.ViewState["DataBound"]?==?null)
????????????{
????????????????if?(!this.Page.IsPostBack)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????????else?if?(base.IsViewStateEnabled)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????}
????????????base.OnLoad(e);
????????}
好了,基本代碼的編寫就完成了,接著你就可以通過設置DataSource屬性手動綁定的形式和設置DataSourceID屬性獲取數據源的形式獲取數據了。
這篇可以供參考,如果真要這么做的話,幾乎每個原有的數據綁定控件都需要重復編寫上面這么多代碼。相比之下如DataBoundControl類和BaseDataList類都已經幫你完成了上面的工作,在有選擇的情況下,我們當然不愿意寫上面這么多的代碼。所以說上面的這堆代碼也只供你參考,能夠使用新的基類的話,盡量使用,如果真的需要這么做的話,你就需要這么去改你的數據綁定控件。
這篇可能講的不是很詳細,大家如果真的有必要這么做的話,可以仔細看看。不足之處還請大家糾正^_^.
晚了,睡覺去了。
?????? 上篇介紹了在asp.net2.0版本下面如何簡單的定義數據綁定控件。雖然DataBoundControl為我們提供了便利,我們以后可以從此類開始編寫數據綁定控件。但是在2.0版本未到來之前,你已經為自己訂制了一些數據綁定控件,既然2.0版本已經提供了數據源控件,你是否有想法,讓你原有的控件也升級到同時支持通過設置DataSource屬性和數據源控件來獲取數據源,這樣以后我們就可以省省工作了。這次我們就來討論這個話題,讓舊版本的數據綁定控件支持數據源控件。
一.準備升級數據綁定控件
即使asp.net1.1版本的一些控件也都已經支持數據源控件了,如Repeater,BaseDataList等.但本身這些對象并不是從BaseDataBoundControl和DataBoundControl等類繼承下來的,如Repeater其是從Control下繼承的一個模板控件,其并不需要這么多從WebControl繼承下來的屬性,如果你想讓它支持數據源控件,你首先會想到改變控件基類,從DataBoundControl開始,這是一個好想法,但可能有些情況下并不允許這么做。上次說到了BaseDataList和DataBoundControl,BaseDataList也支持數據源控件了,所以我認為從此類繼承是完全沒有問題的。另外的做法就是在不改變原有控件基類的情況下,你還是需要老老實實給原控件添加一些代碼支持數據源控件。那么就開始吧.
二.具體實現
本次例子跟上篇相同,相同地方就略過了
1.定義基本成員
整個控件的實現方式跟DataBoundControl實現方式很相似,我們可以看看MSDN中,BaseDataList等基類添加了哪些元素,然后模仿著實現.如果對BaseDataBoundControl和DataBoundControl這兩個類成員了解的話,你將對下面成員屬性很熟悉,添加這些基本成員
(1)
???????/**////?<summary>
????????///?該值指示控件是否已經初始化
????????///?</summary>
????????protected?bool?Initialized
????????{
????????????get
????????????{
????????????????return?initialized;
????????????}
????????}
???????public?string?DataMember
???????{
???????????get
???????????{
???????????????object?member?=?ViewState["DataMember"];
???????????????if?(member?==?null)
???????????????????return?string.Empty;
???????????????else
???????????????????return?(string)member;
???????????}
???????????set
???????????{
???????????????ViewState["DataMember"]?=?value;
???????????????this.OnDataPropertyChanged();
???????????}
???????}
????????/**////?<summary>
????????///?為數據綁定控件提供數據源
????????///?</summary>
???????public?IEnumerable?DataSource
???????{
???????????get
???????????{
???????????????return?dataSource;
???????????}
???????????set
???????????{
???????????????if?((value?is?IEnumerable)?||?(value?is?IListSource)?||?(value?==?null))
???????????????????dataSource?=?value;
???????????????else
???????????????????throw?new?Exception("錯誤的數據源類型");
???????????????OnDataPropertyChanged();
???????????}
???????}
????????/**////?<summary>
????????///?數據源控件的?ID?屬性
????????///?</summary>
????????[DefaultValue(""),?IDReferenceProperty(typeof(DataSourceControl))]
????????public?virtual?string?DataSourceID
????????{
????????????get
????????????{
????????????????object?dataSourceID?=?ViewState["DataSourceID"];
????????????????if?(dataSourceID?!=?null)
????????????????{
????????????????????return?(string)dataSourceID;
????????????????}
????????????????return?string.Empty;
????????????}
????????????set
????????????{
????????????????this.ViewState["DataSourceID"]?=?value;
????????????????this.OnDataPropertyChanged();
????????????}
????????}
????????/**////?<summary>
????????///?獲取是否設置?DataSourceID?屬性的值
????????///?</summary>
????????protected?bool?IsBoundUsingDataSourceID
????????{
????????????get
????????????{
????????????????return?(DataSourceID.Length?>?0);
????????????}
????????}
????????/**////?<summary>
????????///?是否需要綁定到其指定的數據源
????????///?</summary>
????????protected?bool?RequiresDataBinding
????????{
????????????get
????????????{
????????????????return?requiresDataBinding;
????????????}
????????????set
????????????{
????????????????requiresDataBinding?=?value;
????????????}
????????}
????????/**////?<summary>
????????///?用于檢索數據的?DataSourceSelectArguments?對象。默認為?Empty?值
????????///?</summary>
????????protected?DataSourceSelectArguments?SelectArguments
????????{
????????????get
????????????{
????????????????if?(selectArguments?==?null)
????????????????{
????????????????????selectArguments?=?CreateDataSourceSelectArguments();
????????????????}
????????????????return?selectArguments;
????????????}
????????}
(2)上面幾個屬性涉及到幾個方法
???????/**////?<summary>
????????///?創建空的?DataSourceSelectArguments?對象
????????///?</summary>
????????///?<returns></returns>
????????protected?virtual?DataSourceSelectArguments?CreateDataSourceSelectArguments()
????????{
????????????return?DataSourceSelectArguments.Empty;
????????}
???????/**////?<summary>
???????///?如果設置了?DataSourceID?屬性且數據綁定控件標記為需要綁定,則調用?DataBind?方法
????????///?OnPreRender中調用
???????///?</summary>
???????protected?void?EnsureDataBound()
???????{
???????????if?(RequiresDataBinding?&&?(DataSourceID.Length?>?0))
???????????{
???????????????DataBind();
???????????}
???????}
???????
???????/**////?<summary>
???????///?在某一基數據源標識屬性更改后,將數據綁定控件重新綁定到其數據
???????///?</summary>
???????protected?virtual?void?OnDataPropertyChanged()
???????{
???????????if?(initialized)
???????????{
???????????????RequiresDataBinding?=?true;
???????????}
???????????currentViewValid?=?false;
???????}
上面的幾個屬性和方法可以一起來看看了,在更改數據源標識時都會調用OnDataPropertyChanged方法,然后到了EnsureDataBound方法(此方法在OnPreRender方法中調用)在使用數據源控件情況下自動調用DataBind方法。另外Initialized屬性會在控件初始化時設置.
2.獲取與數據綁定控件關聯的 接口
數據源控件實現了IDataSource接口,此接口定義了數據源最基本的元素,數據綁定控件要根據DataSourceID屬性從容器中獲取與其關聯的 接口。如下實現
?????//?從容器中獲取DataControl
???????private?Control?FindControl(Control?control,?string?controlID)
????????{
????????????Control?namingContainer?=?control;
????????????Control?dataControl?=?null;
????????????if?(control?!=?control.Page)
????????????{
????????????????while?((dataControl?==?null)?&&?(namingContainer?!=?control.Page))
????????????????{
????????????????????namingContainer?=?namingContainer.NamingContainer;
????????????????????if?(namingContainer?==?null)
????????????????????{
????????????????????????throw?new?HttpException("DataBoundControlHelper_NoNamingContainer");
????????????????????}
????????????????????dataControl?=?namingContainer.FindControl(controlID);
????????????????}
????????????????return?dataControl;
????????????}
????????????return?control.FindControl(controlID);
????????}
????????/**////?<summary>
????????///?檢索與數據綁定控件關聯的?IDataSource?接口
????????///?</summary>
????????///?<returns></returns>
???????protected?virtual?IDataSource?GetDataSource()
???????{
???????????if?(this.currentDataSource?!=?null)
???????????{
???????????????return?currentDataSource;
???????????}
???????????//獲取數據源控件
???????????IDataSource?source?=?null;
???????????string?controlID?=?DataSourceID;
???????????if?(controlID.Length?!=?0)
???????????{
???????????????Control?control?=?FindControl(this,?controlID);
???????????????source?=?control?as?IDataSource;
???????????}
???????????return?source;
???????}
3.獲取數據源視圖
第二步的實現是為此服務的
????????private?DataSourceView?ConnectToDataSourceView()
????????{
????????????if?(!currentViewValid?||?base.DesignMode)
????????????{
????????????????
????????????????if?((currentView?!=?null)?&&?currentViewIsFromDataSourceID)
????????????????{
????????????????????currentView.DataSourceViewChanged?-=?new?EventHandler(this.OnDataSourceViewChanged);
????????????????}
????????????????this.currentDataSource?=?GetDataSource();
????????????????//從DataSource獲取數據源
????????????????if?(this.currentDataSource?==?null)
????????????????{
????????????????????this.currentDataSource?=?new?ReadOnlyDataSource(DataSource,?DataMember);
????????????????}
????????????????DataSourceView?view?=?this.currentDataSource.GetView(DataMember);
????????????????currentViewIsFromDataSourceID?=?IsBoundUsingDataSourceID;
????????????????currentView?=?view;
????????????????
????????????????if?((currentView?!=?null)?&&?currentViewIsFromDataSourceID)
????????????????{
????????????????????currentView.DataSourceViewChanged?+=?new?EventHandler(this.OnDataSourceViewChanged);
????????????????}
????????????????currentViewValid?=?true;
????????????}
????????????return?currentView;
????????}
????????/**////?<summary>
????????///?獲取數據源視圖
????????///?</summary>
????????///?<returns></returns>
????????protected?virtual?DataSourceView?GetData()
????????{
??????????return?ConnectToDataSourceView();
????????}
請注意ConnectToDataSourceView方法,前后分別在移除和添加一個事件,將RequiresDataBinding屬性設置為true重新綁定,然后再看中間這段代碼
????????????????if?(this.currentDataSource?==?null)
????????????????{
????????????????????this.currentDataSource?=?new?ReadOnlyDataSource(DataSource,?DataMember);
????????????????}
即當未使用數據源控件時,則就從ReadOnlyDataSource對象通過設置DataSource和DataMember屬性來獲取IDataSource 接口,然后才能獲取到數據源視圖.下面為ReadOnlyDataSource和ReadOnlyDataSourceView的簡單實現,在此不做解釋.下次再來講這個東西
???public?class?ReadOnlyDataSource?:?IDataSource
????{
????????
????????private?string?_dataMember;
????????private?object?_dataSource;
????????private?static?string[]?ViewNames?=?new?string[0];
???????
????????event?EventHandler?IDataSource.DataSourceChanged
????????{
????????????add
????????????{
????????????}
????????????remove
????????????{
????????????}
????????}
????????
????????public?ReadOnlyDataSource(object?dataSource,?string?dataMember)
????????{
????????????this._dataSource?=?dataSource;
????????????this._dataMember?=?dataMember;
????????}
????????DataSourceView?IDataSource.GetView(string?viewName)
????????{
????????????IDataSource?source?=?_dataSource?as?IDataSource;
????????????if?(source?!=?null)
????????????{
????????????????return?source.GetView(viewName);
????????????}
????????????return?new?ReadOnlyDataSourceView(this,?this._dataMember,DataSourceHelper.ResolveDataSource(this._dataSource,?this._dataMember));
????????}
????????ICollection?IDataSource.GetViewNames()
????????{
????????????return?ViewNames;
????????}
????}
?public?class?ReadOnlyDataSourceView?:?DataSourceView
????{
????????private?IEnumerable?dataSource;
????????public?ReadOnlyDataSourceView(ReadOnlyDataSource?owner,?string?name,?IEnumerable?dataSource)
????????????:?base(owner,?name)
????????{
????????????this.dataSource=dataSource?;
????????}
????????protected?override?IEnumerable?ExecuteSelect(DataSourceSelectArguments?arguments)
????????{
????????????arguments.RaiseUnsupportedCapabilitiesError(this);
????????????return?dataSource;
????????}
????}
4.獲取數據
接著你便可以在DataBind方法中通過獲取到的數據源視圖異步獲取數據了,本來我們可以調用其ExecuteSelect方法的,可惜我們無法調用此方法,只好異步調用。接著的PerformDataBinding方法跟上篇實現一樣。不再列出
記得在DataBind方法將RequiresDataBinding?屬性設置為true
????????/**////?<summary>
????????///?將數據源綁定到控件
????????///?</summary>
????????public?override?void?DataBind()
????????{
????????????if?(!IsBoundUsingDataSourceID)
????????????{
????????????????OnDataBinding(EventArgs.Empty);
????????????}
????????????GetData().Select(CreateDataSourceSelectArguments(),
????????????????OnDataSourceViewSelectCallback);
????????????RequiresDataBinding?=?false;
????????????MarkAsDataBound();
????????}
????????private?void?OnDataSourceViewSelectCallback(IEnumerable?retrievedData)
????????{
????????????if?(IsBoundUsingDataSourceID)
????????????{
????????????????OnDataBinding(EventArgs.Empty);
????????????}
????????????PerformDataBinding(retrievedData);
????????}
5.重寫控件生命周期事件
其中在OnPreRender方法中調用了EnsureDataBound方法,其他方法的話可以發現在很多不同情況下將RequiresDataBinding和Initialized屬性設置為True.做了數據綁定的初始化工作。這里估計我也解釋不清楚,大家還是了解下控件的生命周期,了解其事件的使用,再理解吧.這里可以參考jessezhao的這篇翻譯
????????protected?override?void?OnInit(EventArgs?e)
????????{
????????????base.OnInit(e);
????????????if?(this.Page?!=?null)
????????????{
????????????????this.Page.PreLoad?+=?new?EventHandler(this.OnPagePreLoad);
????????????????if?(!base.IsViewStateEnabled?&&?this.Page.IsPostBack)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????}
????????}
????????private?void?OnPagePreLoad(object?sender,?EventArgs?e)
????????{
????????????initialized?=?true;
????????????if?(Page?!=?null)
????????????{
????????????????Page.PreLoad?-=?new?EventHandler(OnPagePreLoad);
????????????????if?(!Page.IsPostBack)
????????????????{
????????????????????RequiresDataBinding?=?true;
????????????????}
????????????????if?((Page.IsPostBack?&&?base.IsViewStateEnabled)?&&?(ViewState["DataBound"]?==?null))
????????????????{
????????????????????RequiresDataBinding?=?true;
????????????????}
????????????}
????????}
????????protected?override?void?OnPreRender(EventArgs?e)
????????{
????????????EnsureDataBound();
????????????base.OnPreRender(e);
????????}
????????protected?override?void?OnLoad(EventArgs?e)
????????{
????????????this.initialized?=?true;
????????????this.ConnectToDataSourceView();
????????????if?(this.Page?!=?null?&&?this.ViewState["DataBound"]?==?null)
????????????{
????????????????if?(!this.Page.IsPostBack)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????????else?if?(base.IsViewStateEnabled)
????????????????{
????????????????????this.RequiresDataBinding?=?true;
????????????????}
????????????}
????????????base.OnLoad(e);
????????}
好了,基本代碼的編寫就完成了,接著你就可以通過設置DataSource屬性手動綁定的形式和設置DataSourceID屬性獲取數據源的形式獲取數據了。
這篇可以供參考,如果真要這么做的話,幾乎每個原有的數據綁定控件都需要重復編寫上面這么多代碼。相比之下如DataBoundControl類和BaseDataList類都已經幫你完成了上面的工作,在有選擇的情況下,我們當然不愿意寫上面這么多的代碼。所以說上面的這堆代碼也只供你參考,能夠使用新的基類的話,盡量使用,如果真的需要這么做的話,你就需要這么去改你的數據綁定控件。
這篇可能講的不是很詳細,大家如果真的有必要這么做的話,可以仔細看看。不足之處還請大家糾正^_^.
晚了,睡覺去了。
轉載于:https://www.cnblogs.com/hunterzou/archive/2008/12/19/1358575.html
總結
以上是生活随笔為你收集整理的asp.net控件开发基础(21)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 仿windows造字程序的 ASP.NE
- 下一篇: Visual Studio 2008/.