惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog

博客园 - 【ChengKing(ZhengJian)】

书讯 —《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》第二版 书讯 —《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》第二次印刷已经出版发行 博文视点 市场快讯 09年一季度新书预告 ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—教程索引】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(6)页面状态机制(视图状态和控件状态)】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(5)事件和数据回发机制】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(4)服务器控件属性】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(3)从零开始开发服务器控件】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(2)服务器控件开发中的调试技术】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(1)读者序】★★★ ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术--基于VS 2008(兼容VS 2005)/C#】★★★ Silverlight入门教程(基于Asp.net运行环境示例)[示例代码下载] Asp.net Ajax框架教程[教程下载] JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载] Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载) Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载) Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载) Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSource属性, 能够自动识别不同数据源](示例代码下载) Asp.net 2.0自定义控件开发相关的几种嵌入资源解决方案
Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSour...
【ChengKing(ZhengJian)】 · 2008-04-05 · via 博客园 - 【ChengKing(ZhengJian)】

(一).  概要

          开发<数据绑定用户控件>, 要实现一个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 }

(四). 示例代码下载

(五). 更多自定义控件开发相关文章