Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSource属性, 能够自动识别不同数据源](示例代码下载)

    技术2022-05-11  40

    (一).  概要

              开发 <数据绑定用户控件> , 要实现一个DataSource属性, 并且能够自动识别不同的数据源, 如: ArrayList,

    DataTable, DataSet, XML文件等.

              在书上和网上找了些资料, 它们一般的实现方案是把一些具有DataSource属性的数据控件

    DataList/Reapter等嵌套到用户控件里面实现, 比较容易实现.  但也存在一些问题:

             1. 如果实现很简单的功能, 把一个DataList嵌套在用户控件里面, 有些大才小用, 比较庞大, 产生冗余代码较

                 多, 效率也不会很高.

             2. 缺乏灵活性. 由于嵌套数据绑定控件到用户控件中, 毕竟是"变态"地做法; 这样太依赖现在数据绑定控件,

                 实现某些特殊功能缺乏灵活性, 甚至有些功能受限制而无法实现.

              决定自己写一个.  在用户控件中实现数据源DataSource属性比自定义控件中复杂多了. 自定义控件中, 尤

    其是在 Dot Net 2.0中实现此属性非常简单,  具体是实现 BaseDataBoundControl(数据绑定基类)/

    /DataBoundControl(列表和表格控件基类)和HierarchicalDataBoundControl(开发Tree和Menu基类)等几个

    基类,  再重写几个方法就OK了. 

            但用户控件遇到麻烦, 它默认已经继承了 System.Web.UI.UserControl 用户控件基类, 不能再继承其它

    类了(C#语法规定不允许多继承).   下面这个例子是参考了一个本上的一个自定义控件例子, 修改了一些代码,

    把它改到这个用户控件中了.  网上很难找到用户控件这样的示例, 共享一下.

    控件很简单, 只有DataSource相关的几个属性

    [涉及到公司代码版权问题, 自己单独做了个只有DataSource功能的最简单例子,  文章主旨只讲这个属性] .

    (二). 绑定效果

    (三).  核心代码

    1. 用户控件部分

      1  using  System.ComponentModel;   2  using  System.Xml;   3  using  System.Xml.Schema;   4  using  System.Xml.Serialization;   5    6  ///     7 /// Author: [ ChengKing(ZhengJian) ]   8 /// Blog:   Http://blog.csdn.net/ChengKing  9 ///   10  public  partial  class  LinkList : System.Web.UI.UserControl  11  {  12   13       private   bool  blnMultiTypeDataSource  =   false ;  14   15       #region  属性     16   17   18   19       ///    20     /// 表格每行图像控件的指向图片名称 21     ///   22      [  23       Bindable( true ),  24       Category( " Data " ),  25       DefaultValue( null )  26      ]  27       public   string  DataImageField  28      {  29           get  30          {  31              String s  =  (String)ViewState[ " DataImageField " ];  32               return  ((s  ==   null ?  String.Empty : s);  33          }  34   35           set  36          {  37              ViewState[ " DataImageField " =  value;  38          }  39      }  40   41       ///    42     /// 表格每行链接控件显示的文本 43     ///        44      [  45       Bindable( true ),  46       Category( " Data " ),  47       DefaultValue( null )  48      ]  49       public   string  DataTextField  50      {  51           get  52          {  53              String s  =  (String)ViewState[ " DataTextField " ];  54               return  ((s  ==   null ?  String.Empty : s);  55          }  56   57           set  58          {  59              ViewState[ " DataTextField " =  value;  60          }  61      }  62   63       ///    64     /// 表格第行链接控件的跳转目标页面链接 65     ///   66      [  67       Bindable( true ),  68       Category( " Data " ),  69       DefaultValue( null )  70      ]  71       public   string  DataLinkToField  72      {  73           get  74          {  75              String s  =  (String)ViewState[ " DataLinkToField " ];  76               return  ((s  ==   null ?  String.Empty : s);  77          }  78   79           set  80          {  81              ViewState[ " DataLinkToField " =  value;  82          }  83      }  84   85       ///    86     /// 表格每行的链接目标页面打开方式 87     ///   88      [  89       Bindable( true ),  90       Category( " Data " ),  91       DefaultValue( null )  92      ]  93       public   string  DataLinkTargetField  94      {  95           get  96          {  97              String s  =  (String)ViewState[ " DataLinkTargetField " ];  98               return  ((s  ==   null ?  String.Empty : s);  99          } 100  101           set 102          { 103              ViewState[ " DataLinkTargetField " =  value; 104          }  105      } 106  107       private   object  _dataSource; 108  109      [ 110       Bindable( true ),      111       Category( " Data " ), 112       DefaultValue( null ), 113       Description( " 获取或设置数据源 " ), 114       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 115      ] 116       public   virtual   object  DataSource 117      { 118           get 119          { 120               return  _dataSource; 121          } 122           set 123          { 124               if  ((value  ==   null ||  (value  is  IListSource)  ||  (value  is  IEnumerable)) 125              { 126                  _dataSource  =  value; 127              } 128               else 129              { 130                   throw   new  ArgumentException(); 131              } 132          } 133      } 134  135      [ 136          Category( " Data " ), 137          DefaultValue( "" ), 138          Description( " 获取或者设置绑定的数据成员. " ) 139      ] 140       public   virtual   string  DataMember 141      { 142           get 143          { 144               string  s  =  ( string )ViewState[ " DataMember " ]; 145               return  (s  ==   null ?  String.Empty : s; 146          } 147           set 148          { 149              ViewState[ " DataMember " =  value; 150          } 151      } 152  153      [ 154       Bindable( true ), 155       Category( " Data " ), 156       DefaultValue( null ), 157       Description( " 获取或设置XML文件路径 " ), 158       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 159      ] 160       public   virtual   string  XMLDataFile 161      { 162           get 163          { 164               string  s  =  ( string )ViewState[ " XMLDataFile " ]; 165               return  (s  ==   null ?  String.Empty : s; 166          } 167           set 168          { 169              ViewState[ " XMLDataFile " =  value; 170          } 171      } 172  173      [ 174           Bindable( true ), 175           Category( " Data " ), 176           DefaultValue( null ), 177           Description( " 获取或设置XML模式文件路径 " ), 178           DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 179     ] 180       public   virtual   string  XMLSchemaFile 181      { 182           get 183          { 184               string  s  =  ( string )ViewState[ " XMLSchemaFile " ]; 185               return  (s  ==   null ?  String.Empty : s; 186          } 187           set 188          { 189              ViewState[ " XMLSchemaFile " =  value; 190          } 191      } 192  193       #endregion 194  195       protected   override   void  CreateChildControls() 196      { 197          Controls.Clear(); 198          CreateControlHierarchy(); 199           base .CreateChildControls(); 200      } 201  202       protected   virtual   void  CreateControlHierarchy() 203      { 204          Table tbParent  =   new  Table(); 205          tbParent.Attributes.Add( " Cellpadding " " 0 " ); 206          tbParent.Attributes.Add( " Cellspacing " " 0 " );   207  208          IEnumerable dataSource  =   null ; 209           int  rowCount  =   0 ; 210           int  columnCount  =   0 ;         211          dataSource  =  GetDataSource();        212  213           if  (dataSource  !=   null ) 214          {             215              PropertyDescriptor[] properties  =   null ; 216               foreach  ( object  dataItem  in  dataSource) 217              {                218                  properties  =  GetColumnPropertyDescriptors(dataItem); 219                  columnCount  =  properties.Length;                                                     220  221                   for  ( int  i  =   0 ; i  <  (columnCount  -   3 ); i ++ ) 222                  { 223                       if  (blnMultiTypeDataSource  ==   false ) 224                      { 225                          PropertyDescriptor pdImage  =  properties[i]; 226                           object  cellImage  =  pdImage.GetValue(dataItem); 227                           string  imageSrc  =  ( string )pdImage.Converter.ConvertTo(cellImage,  typeof ( string )); 228  229                          PropertyDescriptor pdText  =  properties[i  +   2 ]; 230                           object  cellText  =  pdText.GetValue(dataItem); 231                           string  text  =  ( string )pdText.Converter.ConvertTo(cellText,  typeof ( string )); 232  233                          PropertyDescriptor pdLinkTo  =  properties[i  +   3 ]; 234                           object  cellLinkTo  =  pdLinkTo.GetValue(dataItem); 235                           string  linkTo  =  ( string )pdLinkTo.Converter.ConvertTo(cellLinkTo,  typeof ( string )); 236  237                          PropertyDescriptor pdLinkTarget  =  properties[i  +   1 ];                         238                           object  cellLinkTarget  =  pdLinkTarget.GetValue(dataItem);                         239                           string  linkTarget  =  ( string )pdLinkTarget.Converter.ConvertTo(cellLinkTarget,  typeof ( string )); 240  241                          ItemRow item  =   new  ItemRow(imageSrc, text, linkTo, linkTarget); 242  243                          tbParent.Controls.Add(item); 244                      } 245                       else 246                      { 247                           string  imageSrc  =   "" ; 248                           string  text  =   "" ; 249                           string  linkTo  =   "" ; 250                           string  linkTarget  =   "" ; 251                           for  ( int  j  =   0 ; j  <  columnCount; j ++ ) 252                          { 253                              PropertyDescriptor pd  =  properties[j]; 254                               object  objValue  =  pd.GetValue(dataItem); 255                               string  strValue  =  ( string )pd.Converter.ConvertTo(objValue,  typeof ( string )); 256                               if  (String.Compare(pd.Name,  this .DataImageField,  true ) == 0 ) 257                              { 258                                  imageSrc  =  strValue; 259                              } 260                               if  (String.Compare(pd.Name,  this .DataTextField,  true ) == 0 ) 261                              { 262                                  text  =  strValue; 263                              } 264                               if  (String.Compare(pd.Name,  this .DataLinkToField,  true ) == 0 ) 265                              { 266                                  linkTo  =  strValue; 267                              } 268                               if  (String.Compare(pd.Name,  this .DataLinkTargetField,  true ) == 0 ) 269                              { 270                                  linkTarget  =  strValue; 271                              }                             272                          } 273                          ItemRow item  =   new  ItemRow(imageSrc, text, linkTo, linkTarget); 274                          tbParent.Controls.Add(item); 275                      } 276                  } 277                  278                   this .Controls.Add(tbParent);  279                  rowCount ++ ; 280              } 281          } 282          283           if  ( this .XMLDataFile + String.Empty  !=  String.Empty) 284          { 285              XmlReaderSettings settings  =   new  XmlReaderSettings(); 286              settings.IgnoreWhitespace  =   true ; 287              settings.IgnoreComments  =   true ; 288              NameTable nt  =   new  NameTable(); 289               string  link  =  nt.Add( " link " ); 290              settings.NameTable  =  nt; 291               292               // 验证 293              settings.Schemas.Add( null , XmlReader.Create( this .XMLSchemaFile)); 294              settings.ValidationType  =  ValidationType.Schema; 295              settings.ValidationFlags  =  XmlSchemaValidationFlags.ReportValidationWarnings; 296              settings.ValidationEventHandler  +=   new  ValidationEventHandler(settings_ValidationEventHandler); 297               298               // 序列化工厂类 299              XmlSerializerFactory factory  =   new  XmlSerializerFactory(); 300               301               using  (XmlReader reader  =  XmlReader.Create(  this .XMLDataFile, settings)) 302              { 303                   while  (reader.Read()) 304                  { 305                       if  (reader.NodeType  ==  XmlNodeType.Element  &&  String.Compare(link, reader.LocalName, true ) == 0 ) 306                      {                         307                          XmlSerializer xs  =  factory.CreateSerializer( typeof (Link)); 308                          Link l  =  (Link)xs.Deserialize(reader.ReadSubtree()); 309                          ItemRow item  =   new  ItemRow(l.ImageName, l.Text, l.LinkTo, l.LinkTarget); 310                          tbParent.Rows.Add(item); 311                      } 312                  } 313              } 314               this .Controls.Add(tbParent);  315          }         316      } 317  318       ///   319     /// 当设置数据源时, 要验证XML文件格式是否正确;  当格式不正确时,此方法用来处理当XML文件格式不正确时,要进行的操作320     ///  321       ///   322       ///   323       private   void  settings_ValidationEventHandler( object  sender, System.Xml.Schema.ValidationEventArgs e) 324      { 325           throw   new  Exception( " 数据文件:  "   +   this .XMLDataFile  +   "  格式不正确! [ "   +  e.Message  +   " ] " ); 326      } 327  328       protected   override   void  Render(HtmlTextWriter writer) 329      {        330           base .Render(writer);         331      } 332      333       public   override   void  DataBind() 334      {        335           base .OnDataBinding(EventArgs.Empty); 336          Controls.Clear(); 337          ClearChildViewState(); 338          TrackViewState();         339          CreateControlHierarchy(); 340          ChildControlsCreated  =   true ; 341      } 342  343       private  PropertyDescriptor[] GetColumnPropertyDescriptors( object  dataItem) 344      { 345          ArrayList props  =   new  ArrayList(); 346          PropertyDescriptorCollection propDescs  =  TypeDescriptor.GetProperties(dataItem); 347           foreach  (PropertyDescriptor pd  in  propDescs) 348          { 349              Type propType  =  pd.PropertyType; 350              TypeConverter converter  =  TypeDescriptor.GetConverter(propType); 351               if  ((converter  !=   null &&  converter.CanConvertTo( typeof ( string ))) 352              { 353                  props.Add(pd); 354              } 355          }         356          PropertyDescriptor[] columns  =   new  PropertyDescriptor[props.Count]; 357          props.CopyTo(columns,  0 ); 358           return  columns; 359      } 360  361  362       // 获取数据源,将数据源中的数据都转换为IEnumerable类型 363       protected   virtual  IEnumerable GetDataSource() 364      { 365           if  (_dataSource  ==   null ) 366          { 367               return   null ; 368          } 369          IEnumerable resolvedDataSource  =  _dataSource  as  IEnumerable; 370           if  (resolvedDataSource  !=   null ) 371          { 372               return  resolvedDataSource;  // 强类型集合类型/ArrayList 373          } 374  375           this .blnMultiTypeDataSource  =   true ; 376  377          IListSource listSource  =  _dataSource  as  IListSource; 378           if  (listSource  !=   null ) 379          { 380              IList memberList  =  listSource.GetList(); 381  382               if  (listSource.ContainsListCollection  ==   false ) 383              { 384                   return  (IEnumerable)memberList;  // DataTable 385              } 386              ITypedList typedMemberList  =  memberList  as  ITypedList; 387               if  (typedMemberList  !=   null ) 388              { 389                  PropertyDescriptorCollection propDescs  =  typedMemberList.GetItemProperties( new  PropertyDescriptor[ 0 ]); 390                  PropertyDescriptor memberProperty  =   null ; 391  392                   if  ((propDescs  !=   null &&  (propDescs.Count  !=   0 )) 393                  { 394                       string  dataMember  =  DataMember; 395  396                       if  (dataMember.Length  ==   0 ) 397                      { 398                          memberProperty  =  propDescs[ 0 ]; 399                      } 400                       else 401                      { 402                          memberProperty  =  propDescs.Find(dataMember,  true ); 403                      } 404  405                       if  (memberProperty  !=   null ) 406                      { 407                           object  listRow  =  memberList[ 0 ]; 408                           object  list  =  memberProperty.GetValue(listRow); 409  410                           if  (list  is  IEnumerable) 411                          { 412                               return  (IEnumerable)list;  // DataSet 413                          } 414                      } 415                       throw   new  Exception( " 未能找到有效的DataMember. " ); 416                  } 417  418                   throw   new  Exception( " 数据源中不包含任何数据对象. " ); 419              } 420          } 421           return   null ; 422      }         423  }

    2. 使用不同数据源绑定

     1  ///    2 /// Author: [ ChengKing(ZhengJian) ]  3 /// Blog:   Http://blog.csdn.net/ChengKing 4 ///   5  public  partial  class  _Default : System.Web.UI.Page   6  {     7       protected   void  Page_Load( object  sender, EventArgs e)  8      {  9           ///   10         /// 测试通过各种数据源进行绑定11         ///  12  13           // (一). 绑定强类型集合类型 14          ItemList itemList  =   new  ItemList(); 15          itemList.Add( new  Item( @" Images/img.gif " " 宁波宇泰软件股份有限公司 " " http://www.xframe.com.cn " " blank " )); 16          itemList.Add( new  Item( @" Images/img.gif " " 宁波宇泰软件开发有限公司 " " http://www.xframe.com.cn " " blank " )); 17          DataSourceInUserControl1.DataSource  =  itemList; 18          DataSourceInUserControl1.DataBind(); 19  20           // (二). 绑定ArraList集合类型 21          ArrayList al  =   new  ArrayList(); 22          al.Add( new  Item( @" Images/img.gif " " 宁波宇泰软件股份有限公司 " " http://www.xframe.com.cn " " blank " )); 23          al.Add( new  Item( @" Images/img.gif " " 宁波宇泰软件开发有限公司 " " http://www.xframe.com.cn " " blank " )); 24          DataSourceInUserControl1.DataSource  =  al; 25          DataSourceInUserControl1.DataBind(); 26  27           // (三). 测试绑定DataTable 28          DataTable dt  =   new  CusDataSource().CreateDataTable(); 29          DataSourceInUserControl1.DataSource  =  dt; 30          DataSourceInUserControl1.DataImageField  =   " ImageName " ; 31          DataSourceInUserControl1.DataTextField  =   " Text " ; 32          DataSourceInUserControl1.DataLinkToField  =   " LinkTo " ; 33          DataSourceInUserControl1.DataLinkTargetField  =   " LinkTarget " ; 34          DataSourceInUserControl1.DataBind(); 35  36           // (四). 测试绑定DataSet 37          DataSet ds  =   new  CusDataSource().CreateDataSet(); 38          DataSourceInUserControl1.DataSource  =  ds; 39          DataSourceInUserControl1.DataMember  =  ds.Tables[ 0 ].TableName;  // 如果不声明此句,会默认取DataSet中的第一个表 40          DataSourceInUserControl1.DataImageField  =   " ImageName " ; 41          DataSourceInUserControl1.DataTextField  =   " Text " ; 42          DataSourceInUserControl1.DataLinkToField  =   " LinkTo " ; 43          DataSourceInUserControl1.DataLinkTargetField  =   " LinkTarget " ; 44          DataSourceInUserControl1.DataBind();  45  46           /// /(五). 测试绑定XML 47           string  strDataFile  =  Path.Combine(Request.PhysicalApplicationPath,  " LinkList.xml " ); 48           string  strSchemaFile  =  Path.Combine(Request.PhysicalApplicationPath,  " LinkList.xsd " ); 49          DataSourceInUserControl1.XMLDataFile  =  strDataFile; 50          DataSourceInUserControl1.XMLSchemaFile  =  strSchemaFile; 51      } 52  }            (四). 示例代码下载               http://www.cnblogs.com/Files/MVP33650/DataSource of UserControl.rar          (五). 更多自定义控件开发相关文章                http://blog.csdn.net/ChengKing/category/288694.aspx    

     

     

          

     

     

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1610497


    最新回复(0)