在以上代码中,对每个控件进行显式转换,并将其设置为窗体控件的正确属性。根据属性和窗体控件的数量,这部分代码可能会变长并难以管理。代码还应包含类型转换的错误更正和 ListControl,这将进一步增加复杂性。即使窗体是由代码生成工具(例如 Eric J. Smith 的优秀的 CodeSmith)生成的,当需要任何自定义逻辑关系时,很容易引入错误。
此代码可用于所有标准的 ASP.NET 控件(TextBox、DropDownList、CheckBox 等)和许多第三方控件(例如 Free TextBox 和 Calendar Popup)。无论有多少业务对象属性和窗体控件,这一行代码都能提供所需的全部功能,只要窗体控件的 ID 与业务对象属性名相匹配。
开始:从反射中检索属性列表
首先,我们需要检查业务对象的属性,并查找与业务对象属性名具有相同 ID 的 ASP.NET 控件。以下代码构成了绑定查找的基础:
public class FormBinding { public static void BindObjectToControls(object obj, Control container) { if (obj == null) return; Type objType = obj.GetType(); PropertyInfo[] objPropertiesArray = objType.GetProperties();
foreach (PropertyInfo objProperty in objPropertiesArray) {
Control control = container.FindControl(objProperty.Name); if (control != null) { // 处理控件 ... } } } }
在以上代码中,方法 BindObjectsToControls 接受了业务对象 obj 和一个容器控件。容器控件通常是当前 Web 窗体的 Page 对象。如果所用版本是会在运行时更改控件嵌套顺序的 ASP.NET 1.x MasterPages,您将需要指定窗体控件所在的 Content 控件。这是在 ASP.NET 1.x 中,FindControl 方法对嵌套控件和命名容器的处理方式导致的。
在以上代码中,我们获取了业务对象的 Type,然后使用该 Type 来获取 PropertyInfo 对象的数组。每个 PropertyInfo 对象都包含关于业务对象属性以及从业务对象获取和设置值的能力的信息。我们使用 foreach 循环检查具有与业务对象属性名 (PropertyInfo.Name) 对应的 ID 属性的 ASP.NET 控件的容器。如果找到控件,则尝试将属性值绑定到该控件。
if (control is ListControl) { ListControl listControl = (ListControl) control; string propertyValue = objProperty.GetValue(obj, null).ToString(); ListItem listItem = listControl.Items.FindByValue(propertyValue); if (listItem != null) listItem.Selected = true; } else if (control is CheckBox) { if (objProperty.PropertyType == typeof(bool)) ((CheckBox) control).Checked = (bool) objProperty.GetValue(obj, null); } else if (control is Calendar) { if (objProperty.PropertyType == typeof(DateTime)) ((Calendar) control).SelectedDate = (DateTime) objProperty.GetValue(obj, null); } else if (control is TextBox) { ((TextBox) control).Text = objProperty.GetValue(obj, null).ToString(); } else if (control is Literal)( //... 等等。还可用于标签等属性。 }
此方法完整地涵盖了标准的 ASP.NET 1.x 控件。从这个角度来看,我们拥有了功能齐全的 BindObjectToControls 方法。但在起作用的同时,此方法的应用范围会受到限制,因为它仅考虑内置的 ASP.NET 1.x 控件。如果要支持新的 ASP.NET 2.0 控件,或者要使用任何第三方控件,我们必须在 FormBinding 项目中引用控件的程序集,并将控件类型添加到 if ... else 列表。