日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

asp.net控件开发基础(21)

發布時間:2025/3/20 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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類都已經幫你完成了上面的工作,在有選擇的情況下,我們當然不愿意寫上面這么多的代碼。所以說上面的這堆代碼也只供你參考,能夠使用新的基類的話,盡量使用,如果真的需要這么做的話,你就需要這么去改你的數據綁定控件。

這篇可能講的不是很詳細,大家如果真的有必要這么做的話,可以仔細看看。不足之處還請大家糾正^_^.
晚了,睡覺去了。

轉載于:https://www.cnblogs.com/hunterzou/archive/2008/12/19/1358575.html

總結

以上是生活随笔為你收集整理的asp.net控件开发基础(21)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。