(一). 概要
开发, 要实现一个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. 用户控件部分
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 +=