我目前有一个TabControl
包含一些TabPage
s 的表单。每个TabPage
都有几个带有验证逻辑和适当ErrorProvider
s 的控件。在我的OK_Button_Clicked
活动中,我打电话Form.ValidateChildren()
以确定是否保存和关闭表单。现在,假设我在选项卡 1 中有一个未通过验证的控件,但当前可见的选项卡是选项卡 2。当用户按 OK 时,他不会得到关于表单未关闭原因的视觉指示。我希望能够自动切换到验证失败的选项卡,这样用户就会看到ErrorProvider
' 的错误指示。
一种方法是订阅所有适当控件的Validated
和validating
事件,并知道每个控件在哪个选项卡中,每当验证失败时,可以构建验证失败的选项卡列表。由于ValidationFailed
据我所知没有生成任何事件,这可能很麻烦(例如,为每个控件定义一个布尔值,在验证之前将其设置为 false 并将其Validated
事件设置为 true)。即使我有这样的事件,我也将被迫侦听许多验证事件,每个控件可能验证失败,并在代码中维护未验证选项卡的列表。我应该在这里指出,直接订阅TabPage
's 的验证事件是行不通的,因为即使其中包含的控件验证失败,它们也会作为验证通过。
TabPage
另一种方法可以利用我的控件恰好是自定义控件这一事实。然后我可以让他们实现一个接口,例如:
interface ILastValidationInfoProvider
{
public bool LastValidationSuccessful {get; set;}
}
例如:
public MyControl : UserControl, ILastValidationInfoProvider
{
MyControl_Validing(object sender, object sender, CancelEventArgs e)
{
if (this.PassesValidation())
this.ErrorProvider.SetError(sender, null);
LastValidationSuccessful = true;
else
e.Cancel = true;
this.ErrorProvider.SetError("Validation failed!", null);
LastValidationSuccessful = false;
}
}
然后,在调用之后,ValidateChildren
我可以使用以下代码:
public void OK_Button_Click
{
if (form.ValidateChildren())
this.Close()
else
foreach (TabPage tab in this.TabControl)
foreach (Control control in tab.Controls)
{
ValidationInfo = control as ILastValidationInfoProvider
if (ValidationInfo != null && !ValidationInfo.LastValidationSuccessful)
{
this.TabControl.SelectTab(tab);
return;
}
}
}
我更喜欢这种方法,但它不适合正在验证的控件不是自定义的情况。
我很乐意使用更好的方法。有任何想法吗?
编辑我正在使用Form.AutoValidate = EnableAllowFocusChange
(正如 Chris Sells 在他的 WinForms 书中所推荐的那样),因此焦点确实可以从验证失败的控件(包括移动到其他选项卡)中改变。我还更新了自定义控件的示例代码,以强调其ErrorProvider
内部驻留的事实。