图 2 显示绑定错误 (单击该图像获得较大视图)
BindingError 可以由控件在绑定或取消绑定过程中自动生成,也可以在您的代码中手动将其添加到 BindingErrors 集合中。如果输入值不能转换回被绑定的数据项或属性(通常因为数据转换错误),则会自动生成 BindingError。例如,图 2 中显示的 Reorder Expected 日期是一个无效日期,由于数据转换失败,因此控件将自动捕获该错误。每个 DataBindingItem 还具有 IsRequired 属性,毫无疑问,标记为 IsRequired 的项不能留作空白。如果有这样的项被保留为空白,将自动生成绑定错误并将该错误添加到 BindingErrors 中。
该窗体上的其他两处错误都是人为错误。Dairy Products 错误将通过与 wwDataBinder 关联的 ValidateControl 事件进行处理。对于每个绑定的控件,都将引发该事件,并且事件处理程序允许在对控件取消绑定后对每个控件进行检查。如果确定代码中的某个值无效,则可以通过编程方式来设置 BindingItem 的 BindingErrorMessage 以使其返回 false,以便让联编程序知道该 DataBindingItem 存在错误并需要显示在错误列表上。
最后一个错误纯粹是一个编程意义上的错误,它是通过在 Page 代码中使用 wwDataBinder.AddBindingError 并指定错误消息以及 Control 实例或 ID 来添加
- 6 -
的。这样做可以向绑定了数据的控件分配任意错误消息,并可以使控件带着错误图标显示,并出现在错误列表中。
所有这些都是为了完全以编程方式生成自动绑定错误,从而为错误和错误图标的显示方式带来了巨大的灵活性。另外,该控件会自动在页面上提取任何验证程序控件及其错误消息和控件 ID 并将它们合并到绑定错误机制中。
如果某个控件发生错误,则在默认情况下,该控件的旁边将显示一个图标。显示也可以不显示,您可以从整体上关闭 DataBinder 的警告图标,也可以通过 ErrorMessageLocation 属性更改各个 DataBindingItem 的位置和格式。默认情况下,将使用 WebResource,它指向已编译控件程序集中的嵌入式图像资源。还可以使用 wwDataBinder 上的 ErrorIconUrl 属性显式替代该图像。
该程序集还包含用于显示错误摘要的 wwErrorDisplay 控件,如图 2 所示。该控件是可选的,但我喜欢用它来实现一致性。在示例中,我只是将 BindingErrors.ToHtml 方法的字符串输出分配给 text 属性。该控件还具有简单的消息显示方法(例如 ShowError 和 ShowMessage),它们显示一行消息和一个图标,为在页面上显示消息提供了一致的方式。
您将注意到,错误摘要中提供了每个所显示错误的链接。通过这些链接可跳转到发生错误的各个控件并使其突出显示,从而有助于找到错误和修复错误。
- 7 -
MSDN Magazine
December 2006 Rick Strahl
Simplify Data Binding In ASP.NET 2.0 With Our Custom Control
ASP.NET 2.0 includes many new data binding features that can significantly simplify a variety of data binding scenarios. Unfortunately, one very common scenario-simple control data binding-has changed very little. While this is a common scenario in forms-based Web applications, it remains for the most part a manual and time-consuming process.
Simple control data binding refers to the process of binding a single value to a property of a control-for instance, binding form controls like textboxes, checkboxes, radio buttons, or selected values of list controls to individual data or object values. This could benefit significantly from a consistent approach to handling data binding deterministically, as well as managing error trapping and display consistently. In this article, I introduce a custom extender control that can be used to bind any individual value from data or objects to any control property. It can extend and provide designer support for any existing control on a Web Form.
In the process, I'll demonstrate a flexible and intuitive approach that provides consistent behavior for data binding and unbinding, validation, error handling, and error display in forms-based Web interfaces. I'll also dig into the details of how the control is built and describe some of the interesting benefits.
The wwDataBinder control addresses simple control data binding. In more concrete terms, the control manages bindings that express concepts such as \of the DataRow's CompanyName field to the TextBox's Text property\Item.Entity.Pk property to the SelectedValue property of a DropDown list.\The control manages the process of binding the specified data values to the specified control property, as well as unbinding the value back into the underlying data item. This is true two-way data binding.
The Problem with Stock Data Binding
- 8 -
ASP.NET natively provides you with reasonable support for inbound data binding. Its native data binding expressions use <%# Eval(\page level expressions like <%# this.Item.Entity.Description %> to bind data to control properties. You call the DataBind method on the page or any control of the page to initiate the data binding process. This works well for inbound binding.
However, unbinding and getting the data back into the underlying data fields or properties is not as readily available. ASP.NET 2.0 introduces the GridView, FormView, and DetailsView controls, which let you use <%# Bind(\syntax that provides two-way data binding. Unfortunately, these controls are closely tied to an underlying data source control, which must be IEnumerable-based. So binding to an individual entity object, for example, is not supported.
Perhaps the most serious problem with the native unbinding mechanisms is the way that unbinding errors are handled. If there's a problem with the formatting of an input field-say a numeric field that contains an alpha character or a DateTime value that sets a month of 22-you get a page-level exception when you try to save the value. While you can trap the exception in page-level error handling, you can't summarize this information because the first exception will stop the unbinding process. If you have two or three errors on the page, it will take multiple post backs to handle these errors, which is very unattractive from a UI perspective (though you could use validators to prevent, rather than handle, the problem).
Introducing a Two-Way Data Binding Control
I created the wwDataBinder control to manage simple data binding in a more flexible (and I hope more logical) way. The control provides a number of handy features and capabilities:
Support for deterministic two-way data binding
Binding single object or data values to a control property Unbinding control properties to object or data values Handling data conversion from text to typed data Managing any binding errors in a BindingErrors collection
- 9 -
Support for custom validation events Checking for required values in input Displaying error icons next to controls
Showing message summary with links to controls Adding binding errors programmatically
To use the control, you simply drop it into an ASP.NET page. The control acts as an extender control for any existing controls on the form, and it adds a DataBindingItem property to the extended control in the Visual Studio? 2005 Properties editor (as shown in Figure 1).
Figure 1 Extending Controls with Data Binding Functionality (Click the image for a larger view)
The control sits on the form as a nondescript grey container (you can see this at the bottom of Figure 1), which isn't rendered at run time. It's displayed on the form merely so you can set properties on the wwDataBinder control itself.
As an extender control, wwDataBinder contains a collection of DataBindingItems that hold the configuration values for each of the extended controls. The collection of items is maintained in the HTML markup and the control looks like this:
OnValidateControl=\ - 10 -