我的应用程序中有一个表单,它使用绑定源将控件绑定到模型对象。这样可以工作,并处理基本验证,例如确保用户不会将文本输入到数字字段中。我正在使用ErrorProvider,并设置其datasource =绑定源,以便向用户显示错误消息,这也是有效的。
然而,我无法搞清楚两件事:
如何使用对最终用户更直观的内容覆盖默认错误消息。例如,上面提到的场景中的默认消息是:“输入字符串不是正确的格式”,我希望它说:“年龄必须是正整数。”
如何使用更复杂的业务逻辑轻松扩展此系统。例如,上面的默认处理程序将阻止将字符串作为数字接受,但不会强制执行年龄>默认为0。我知道我可以为每个控件覆盖onValidate,但似乎应该有一种更简单的方法,它依赖于数据模型,而不是单独的控件。
我尝试按如下方式更新我的setter,希望该消息随后显示在使用此模型对象的所有表单/绑定上,但这不起作用:
Public Property Age() As Integer
Get
Return m_age
End Get
Set(ByVal Value As Integer)
If Not IsNumeric(Value) And Value > 0 Then
Throw New ArgumentException("Age must be a positive integer.")
End If
m_age = Value
End Set
End Property
其他想法?
答案 0 :(得分:2)
所以从我所知道的,这几乎是可能的,但由于一些棘手的行为,不能像你想的那样直截了当。问题源于格式化程序和typeconverters吞下/覆盖域对象的错误消息。
这就像我已经接近这一点:
对于您绑定的域对象:
System.ComponentModel.IDataErrorInfo
,返回您想要的用户友好消息。INotifyPropertyChanged
以提醒绑定来源更改。将ErrorProvider.DataSource设置为BindingSource。
为要覆盖默认转化错误消息的每个文本字段添加Validating
事件的处理程序。
手动为控件添加绑定,以便您可以关闭格式。如果您不这样做,格式化程序将吃掉您提供的任何自定义错误消息。所以不要在VS中使用属性编辑器。而是分配绑定ala:
TextBox1.DataBindings.Add("Text", BindingSource1, "Age", False, DataSourceUpdateMode.OnValidation)
如果您执行上述操作,那么只要转换不会导致错误,您的最终用户就会正确查看模型对象的错误消息。如果转换导致错误,他们将会看到您在Validating
处理程序中提供的消息(如果有),或者其他通用消息。
仍然不是一个想法的解决方案,但这是我能得到的尽可能接近。我说不理想,因为这个解决方案阻止你使用自动格式化,并且如果你在多个地方使用模型对象,则要求你在不同的表单上复制一些验证消息。
答案 1 :(得分:1)
下面。这可以节省你吨的工作。
简而言之:要验证绑定控件,您需要处理三个事件。
Control.Validating
事件,用于在用户离开控件时验证数据,Control.Validated
事件,当且仅当它被正确验证时才更新数据源,并且Binding.Parse
事件,当其他任何内容更改控件中的数据(即您的代码)时,它会验证数据。为了确保只有有效数据写入您的数据源,在创建Binding
时关闭绑定数据的自动更新 - 这样,只会将数据 写入Control.Validated
事件期间的数据源。
Validating
和Parse
事件都将验证错误消息放入附加到绑定ErrorProvider
的{{1}};您可能有其他方式想要显示错误消息,在这种情况下,您需要更改这两个事件。
您还可能希望处理绑定的Control
事件,以控制字段中的数据如何在绑定控件中显示。
我没有重写此代码以使其成为通用代码,因为我不想引入任何错误。所以我会解释Format
和fc
是什么,只要你需要知道才能让它发挥作用。
cm
是包装应用程序绑定的fc
对象的类的实例。它有一个Control
属性(显然是包装的控件),然后是Control
和Binding
属性,其用法如下所示。请注意,由于此代码为您设置了数据绑定,因此您不需要在表单设计器中设置控件的绑定。严格来说,你不需要需要这个类才能使这个代码工作,但它确实简化了代码。 (这里的所有代码都来自ErrorProvider
类的静态方法,fc
已经传递给它,如图所示。)
BindingSource
是一个类的实例,其中包含有关我将控件绑定到的数据列的元信息,特别是:
cm
,它在数据源中的名称(我显然是绑定到ColumnName
),DataColumn
,它所绑定的控件属性的名称(例如PropertyName
),"Text"
,如NullValue
,Binding.NullValue
,格式化列的内部值以在绑定控件中显示的方法,Format
,解析输入到列内部值的方法。专栏的实际验证逻辑就在这里。这显然是C#,所以你需要弄乱它才能让它在VB中运行,但差异应该只是语法问题。
Parse
答案 2 :(得分:0)
将错误重新发送给调用方。然后,捕获要“覆盖”的异常类型。不是显示异常消息,而是抛出自定义异常并显示其消息。