一个相当独立的.通用分页控件c#源码二(downmoon收集)

二、核心功能

  当表现控件触发DataBinding事件,分页控件就可以获取DataSource属性。遗憾的是,微软没有提供所 有数据绑定类实现的接口,诸如IdataSourceProvider之类,而且并非所有从Control或WebControl类继承的控件都有一个 DataSource属性,因此向上定型成Control类没有意义,唯一可行的办法是通过Reflection API直接操作DataSoruce属性。在讨论事件句柄方法之前,应该指出的是,为了注册事件句柄,首先必须获得一个表现控件的引用。分页控件显露了一 个简单的字符串属性BindToControl:

一个相当独立的.通用分页控件c#源码二(downmoon收集)public string BindToControl
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
get
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_bindcontrol == null )
一个相当独立的.通用分页控件c#源码二(downmoon收集)
throw new NullReferenceException( " 在使用分页控件之前,请先通过设置BindToControl属性绑定到一个控件。 " );
一个相当独立的.通用分页控件c#源码二(downmoon收集)
return _bindcontrol;}

一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
set ... {_bindcontrol = value;}
一个相当独立的.通用分页控件c#源码二(downmoon收集) }



   这个方法非常重要,所以最好能够抛出一个含义更明确的信息,而不是抛出标准的NullReferenceException异常。在分页控件的 OnInit方法中,我们解析了对表现控件的引用。本例应当用OnInit事件句柄(而不是构造函数)来确保JIT编译的aspx页面已经设置了 BindToControl。

一个相当独立的.通用分页控件c#源码二(downmoon收集)protected override void OnInit(EventArgse)
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) _boundcontrol
= Parent.FindControl(BindToControl);
一个相当独立的.通用分页控件c#源码二(downmoon收集) BoundControl.DataBinding
+= new EventHandler(BoundControl_DataBound);
一个相当独立的.通用分页控件c#源码二(downmoon收集)
base .OnInit(E);
一个相当独立的.通用分页控件c#源码二(downmoon收集) ...
一个相当独立的.通用分页控件c#源码二(downmoon收集) }



   搜索表现控件的操作通过搜索分页控件的Parent控件完成,在这里,Parent就是页面本身。按照这种方式使用Parent比较危险,举例来说,如 果分页控件嵌入到了另一个控件之中,例如嵌入到了Table控件之中,则Parent引用实际上将是一个对Table控件的引用。由于 FindControl方法只搜索当前的控件集合,除非表现控件就在该集合之中,否则不可能搜索到。一种比较安全的方法是递归地搜索各个控件集合,直至找 到目标控件为止。
  找到BoundControl之后,我们将分页控件注册成为DataBinding事件的监听器。由于分页控件要操作数 据源,所以该事件句柄应当是调用链中的最后一个,这一点很重要。不过,只要表现控件在OnInit事件句柄中注册DataBinding的事件句柄(默认 行为),分页控件操作数据源时就不会出现问题。

  DataBound事件句柄负责获取表现控件的DataSource属性。

一个相当独立的.通用分页控件c#源码二(downmoon收集)private void BoundControl_DataBound( object sender,System.EventArgse)
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (HasParentControlCalledDataBinding) return ;
一个相当独立的.通用分页控件c#源码二(downmoon收集) Typetype
= sender.GetType();
一个相当独立的.通用分页控件c#源码二(downmoon收集) _datasource
= type.GetProperty( " DataSource " );
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_datasource == null )
一个相当独立的.通用分页控件c#源码二(downmoon收集)
throw new NotSupportedException( " 分页控件要求表现控件必需包含一个DataSource。 " );
一个相当独立的.通用分页控件c#源码二(downmoon收集)
object data = _datasource.GetGetMethod().Invoke(sender, null );
一个相当独立的.通用分页控件c#源码二(downmoon收集) _builder
= Adapters[data.GetType()];
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_builder == null )
一个相当独立的.通用分页控件c#源码二(downmoon收集)
throw new NullReferenceException( " 没有安装适当的适配器来处理下面的数据源类型: " + data.GetType());
一个相当独立的.通用分页控件c#源码二(downmoon收集) _builder.Source
= data;
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集) ApplyDataSensitivityRules();
一个相当独立的.通用分页控件c#源码二(downmoon收集) BindParent();
一个相当独立的.通用分页控件c#源码二(downmoon收集) RaiseEvent(DataUpdate,
this );
一个相当独立的.通用分页控件c#源码二(downmoon收集) }




   在DataBound中,我们尝试通过Reflection API获得DataSource属性,然后返回实际数据源的一个引用。现在虽然已经获知了数据源,但分页控件还必须知道如何操作该数据源。为了让分页控件 不依赖于特定的表现控件,问题复杂了很多。不过,如果让分页控件依赖于特定的数据源,那就背离了设计一个灵活的分页控件的目标。我们要通过一个接插式的体 系结构来确保分页控件能够处理各种数据源,无论是.NET提供的数据源,还是自定义的数据源。

  为了提供一个健壮的、可伸缩的接插式体系结构,我们将利用[GoF] Builder模式构造出一个解决方案。

一个相当独立的.通用分页控件c#源码二(downmoon收集)



IDataSourceAdapter接口定义了分页控件操作数据所需的最基本的元素,相当于“插头”。

一个相当独立的.通用分页控件c#源码二(downmoon收集)publicinterfaceIDataSourceAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
int TotalCount ... { get ;}
一个相当独立的.通用分页控件c#源码二(downmoon收集)
object GetPagedData( int start, int end);
一个相当独立的.通用分页控件c#源码二(downmoon收集) }



   TotalCount属性返回在处理数据之前数据源所包含元素的总数,而GetPagedData方法返回原始数据的一个子集,例如:假设数据源是一个 包含20个元素的数组,分页控件将数据显示成每页10个元素,则第一页的元素子集是数组元素0-9,第二页的元素子集是数组元素10-19。 DataViewAdapter提供了一个DataView类型的插头:

一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
internal class DataViewAdapter:IDataSourceAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private DataView_view;
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
internal DataViewAdapter(DataViewview)
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) _view
= view;
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public int TotalCount
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
get ... { return (_view == null ) ? 0 :_view.Table.Rows.Count;}
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public object GetPagedData( int start, int end)
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) DataTabletable
= _view.Table.Clone();
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
for ( int i = start;i< = end && i< = TotalCount;i ++ )
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) table.ImportRow(_view[i
- 1 ].Row);
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
return table;
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }



   DataViewAdapter实现了IDataSourceAdapter的GetPagedData方法,该GetPagedData克隆原始的 DataTable,将原始DataTable中的数据导入到新的DataTable。该类的可见性有意地设置成internal,目的是为了向Web开 发者隐藏实现细节,进而通过Builder类提供一个更简单的接口。

一个相当独立的.通用分页控件c#源码二(downmoon收集)public abstract class AdapterBuilder
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private object _source;
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private void CheckForNull()
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_source == null ) throw new NullReferenceException( " 必须提供一个合法的数据源 " );
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public virtual object Source
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
get
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) CheckForNull();
一个相当独立的.通用分页控件c#源码二(downmoon收集)
return _source;}

一个相当独立的.通用分页控件c#源码二(downmoon收集)
set
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) _source
= value;
一个相当独立的.通用分页控件c#源码二(downmoon收集) CheckForNull();
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
public abstract IDataSourceAdapterAdapter ... { get ;}
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)


   AdapterBuilder抽象类为IdataSourceAdapter类型提供了一个更容易管理的接口,由于提高了抽象程度,我们不必再直接使用 IdataSourceAdapter,同时AdapterBuilder还提供了在分页数据之前执行预处理的指令。另外,该Builder还使得实际的 实现类,例如DataViewAdapter,对分页控件的用户透明:

一个相当独立的.通用分页控件c#源码二(downmoon收集)public class DataTableAdapterBuilder:AdapterBuilder
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private DataViewAdapter_adapter;
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private DataViewAdapterViewAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
get
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_adapter == null )
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) DataTabletable
= (DataTable)Source;
一个相当独立的.通用分页控件c#源码二(downmoon收集) _adapter
= new DataViewAdapter(table.DefaultView);
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
return _adapter;
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public override IDataSourceAdapterAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
get
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
return ViewAdapter;
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public class DataViewAdapterBuilder:AdapterBuilder
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private DataViewAdapter_adapter;
一个相当独立的.通用分页控件c#源码二(downmoon收集)
一个相当独立的.通用分页控件c#源码二(downmoon收集)
private DataViewAdapterViewAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)
get
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... { // 延迟实例化
一个相当独立的.通用分页控件c#源码二(downmoon收集)
if (_adapter == null )
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集) _adapter
= new DataViewAdapter((DataView)Source);
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
return _adapter;
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集)
public override IDataSourceAdapterAdapter
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
... {
一个相当独立的.通用分页控件c#源码二(downmoon收集)一个相当独立的.通用分页控件c#源码二(downmoon收集)
get ... { return ViewAdapter;}
一个相当独立的.通用分页控件c#源码二(downmoon收集) }

一个相当独立的.通用分页控件c#源码二(downmoon收集) }