如何覆盖WinForms中数据绑定控件上的错误消息?

时间:2009-02-18 21:29:17

标签: .net vb.net winforms data-binding error-handling

我的应用程序中有一个表单,它使用绑定源将控件绑定到模型对象。这样可以工作,并处理基本验证,例如确保用户不会将文本输入到数字字段中。我正在使用ErrorProvider,并设置其datasource =绑定源,以便向用户显示错误消息,这也是有效的。

然而,我无法搞清楚两件事:

  1. 如何使用对最终用户更直观的内容覆盖默认错误消息。例如,上面提到的场景中的默认消息是:“输入字符串不是正确的格式”,我希望它说:“年龄必须是正整数。”

  2. 如何使用更复杂的业务逻辑轻松扩展此系统。例如,上面的默认处理程序将阻止将字符串作为数字接受,但不会强制执行年龄>默认为0。我知道我可以为每个控件覆盖onValidate,但似乎应该有一种更简单的方法,它依赖于数据模型,而不是单独的控件。

  3. 我尝试按如下方式更新我的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
    

    其他想法?

3 个答案:

答案 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事件期间的数据源。

ValidatingParse事件都将验证错误消息放入附加到绑定ErrorProvider的{​​{1}};您可能有其他方式想要显示错误消息,在这种情况下,您需要更改这两个事件。

您还可能希望处理绑定的Control事件,以控制字段中的数据如何在绑定控件中显示。

我没有重写此代码以使其成为通用代码,因为我不想引入任何错误。所以我会解释Formatfc是什么,只要你需要知道才能让它发挥作用。

cm是包装应用程序绑定的fc对象的类的实例。它有一个Control属性(显然是包装的控件),然后是ControlBinding属性,其用法如下所示。请注意,由于此代码为您设置了数据绑定,因此您不需要在表单设计器中设置控件的绑定。严格来说,你不需要需要这个类才能使这个代码工作,但它确实简化了代码。 (这里的所有代码都来自ErrorProvider类的静态方法,fc已经传递给它,如图所示。)

BindingSource是一个类的实例,其中包含有关我将控件绑定到的数据列的元信息,特别是:

  • cm,它在数据源中的名称(我显然是绑定到ColumnName),
  • DataColumn,它所绑定的控件属性的名称(例如PropertyName),
  • "Text",如NullValue
  • 的文档中所述
  • Binding.NullValue,格式化列的内部值以在绑定控件中显示的方法,
  • Format,解析输入到列内部值的方法。专栏的实际验证逻辑就在这里。

这显然是C#,所以你需要弄乱它才能让它在VB中运行,但差异应该只是语法问题。

Parse

答案 2 :(得分:0)

将错误重新发送给调用方。然后,捕获要“覆盖”的异常类型。不是显示异常消息,而是抛出自定义异常并显示其消息。