winforms - WinForms TabControl验证:switch 到一个验证失败的选项卡

  显示原文与译文双语对照的内容
145 1

我现在有一个带有 TabControl的表单,其中包含一些 TabPage每个 TabPage 都有几个带有验证逻辑和适当 ErrorProvider的控件。OK_Button_Clicked 事件中,调用 Form.ValidateChildren() 以确定是否保存和关闭表单。现在,假设在选项卡 1中有一个控件失败验证,但当前可以见的选项卡为选项卡 2.当用户按下确定时,他将没有视觉指示为什么表单没有关闭。我希望能够自动 switch 到一个验证失败的选项卡,因这里用户会看到错误的ErrorProvider 指示。

一种方法是订阅所有适当控件的Validatedvalidating 事件,并且知道每一个选项卡都在哪里。由于没有生成任何 ValidationFailed 事件,这可能是很麻烦的( 比如 。为每个控件定义一个布尔值,在验证之前将它的设置为 false,并将它的设置为 Validated 事件的true 。即使我有这样的事件,我也会被迫听许多验证事件,每个控件可以能失败。这里我应该注意,直接订阅事件的TabPage 验证不起作用,因为它们的验证失败。

另一种方法可以利用 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;
 }
 }
}

我更喜欢这种方法,但它并不迎合被验证的控件不是自定义的情况。

我愿意用一种更好的方法。有什么想法吗?

我使用的 EDITForm.AutoValidate = EnableAllowFocusChange( 由Chris推荐的that销售),所以焦点确实可以以从失败的验证( 包括移动到其他选项卡)的控件中改变。我还更新了定制控件的示例代码,以强调 ErrorProvider 驻留在它内部的事实。

时间:原作者:0个回答

99 2

好的所以我终于找到了。

我保存一个字典,它的键是 TabPages,而值是对应标签中未验证控件的HashSet通过订阅每个选项卡中控件的所有验证和验证事件,这很容易完成。最后,在 OK_BUtton_Click 中,如果 ValidateChildren 失败了,我知道一个hashsets将是无空的,我只是跳过第一个无。

 Dictionary<TabPage, HashSet<Control>> _tabControls 
 = new Dictionary<TabPage, HashSet<Control>>();
 public OptionsForm()
 { 
 InitializeComponent();
 RegisterToValidationEvents();
 }
 private void RegisterToValidationEvents()
 {
 foreach (TabPage tab in this.OptionTabs.TabPages)
 {
 var tabControlList = new HashSet<Control>();
 _tabControls[tab] = tabControlList;
 foreach (Control control in tab.Controls)
 {
 var capturedControl = control;//this is necessary
 control.Validating += (sender, e) =>
 tabControlList.Add(capturedControl);
 control.Validated += (sender, e) =>
 tabControlList.Remove(capturedControl);
 }
 }
 }
 private void Ok_Button_Click(object sender, EventArgs e)
 {
 if (this.ValidateChildren())
 {
 _settings.Save();
 this.Close();
 }
 else
 {
 var unvalidatedTabs = _tabControls.Where(kvp => kvp.Value.Count!= 0)
. Select(kvp => kvp.Key);
 TabPage firstUnvalidated = unvalidatedTabs.FirstOrDefault();
 if (firstUnvalidated!= null && 
!unvalidatedTabs.Contains(OptionTabs.SelectedTab))
 OptionTabs.SelectedTab = firstUnvalidated;
 }
 }

我觉得这很贴心 !

原作者:
...