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

(一).  概要

          开发<数据绑定用户控件>, 要实现一个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 /// <summary>
  7 /// Author: [ ChengKing(ZhengJian) ] 
  8 /// Blog:   Http://blog.csdn.net/ChengKing
  9 /// </summary>
 10 public partial class LinkList : System.Web.UI.UserControl
 11 {
 12 
 13     private bool blnMultiTypeDataSource = false;
 14 
 15     #region 属性   
 16 
 17 
 18 
 19     /// <summary>
 20     /// 表格每行图像控件的指向图片名称
 21     /// </summary>
 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     /// <summary>
 42     /// 表格每行链接控件显示的文本
 43     /// </summary>    
 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     /// <summary>
 64     /// 表格第行链接控件的跳转目标页面链接
 65     /// </summary>
 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     /// <summary>
 86     /// 表格每行的链接目标页面打开方式
 87     /// </summary>
 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     /// <summary>
319     /// 当设置数据源时, 要验证XML文件格式是否正确;  当格式不正确时,此方法用来处理当XML文件格式不正确时,要进行的操作
320     /// </summary>
321     /// <param name="sender"></param>
322     /// <param name="e"></param>
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 /// <summary>
 2 /// Author: [ ChengKing(ZhengJian) ] 
 3 /// Blog:   Http://blog.csdn.net/ChengKing
 4 /// </summary>
 5 public partial class _Default : System.Web.UI.Page 
 6 {   
 7     protected void Page_Load(object sender, EventArgs e)
 8     {
 9         /// <summary>
10         /// 测试通过各种数据源进行绑定
11         /// </summary>
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 }
    
 
   
(四). 示例代码下载
    
posted @ 2007-08-08 06:43  scgw  阅读(1243)  评论(0编辑  收藏  举报