如何在紧凑框架中强制验证表单/控件?

3

有没有办法在.NET CF中强制控件验证?在完整的.NET中,有Validate()方法,但它在CF中缺失。

我正在尝试使控件在关闭表单时将数据绑定回模型,但单击主菜单按钮似乎无法从控件中夺取焦点,并且Validating和Validated事件不触发。

您知道这个问题的任何解决方法吗?

3个回答

3

大约一年前,我曾经遇到过同样的问题。我在网上找到的所有解决方案都非常糟糕(例如迭代控件并捕获每个控件的焦点,从而触发验证事件,或者依赖于PInvoke或反射的某些解决方案 - 我不太记得了)。

最终,我创建了包含文本框等控件的Validate方法和这些包装器的集合。这样,我可以迭代我的包装器并为每个控件调用validate。

这种解决方案很好用。起初,我尝试了通过编程方式捕获每个控件焦点的解决方案,但是我遇到了很多问题。在浪费了一些时间尝试改进此解决方案后,我决定创建这些包装器,这是一个非常好的决定。

更新

这就是它的外观。请注意,我声明了需要验证的控件列表:

private List<TextBoxWithValidation> textBoxesWithValidation;

在构造函数中,我将控件添加到列表中:
TextBoxWithValidation emailTextBoxWithValidation = new TextBoxWithValidation(emailTextBox);
emailTextBoxWithValidation.AddValidationPair(Validator.ValidationType.VALIDATE_NOT_EMPTY, "ValidateNotEmptyEmail");
emailTextBoxWithValidation.AddValidationPair(Validator.ValidationType.VALIDATE_EMAIL, "ValidateEmailEmail");
textBoxesWithValidation.Add(emailTextBoxWithValidation);

然后,我可以验证表单:

private bool ValidateForm()
{
  foreach (TextBoxWithValidation textBoxWithValidation in textBoxesWithValidation)
  {
    if (!textBoxWithValidation.Validate())
    {
      return false;
    }
  }
  return true;
}

带有验证的文本框如下所示:

class TextBoxWithValidation
{
  class ValidationTypeMessagePair
  {
    public Validator.ValidationType ValidationType { get; set; }
    public string ValidationMessage { get; set; }

    public ValidationTypeMessagePair(Validator.ValidationType validationType, string validationMessage)
    {
      this.ValidationType = validationType;
      this.ValidationMessage = validationMessage;
    }
  }

  private List<ValidationTypeMessagePair> validationPairs;
  private TextBox textBox;

  public TextBoxWithValidation(TextBox textBox)
  {
    this.textBox = textBox;
    this.textBox.DataBindings["Text"].DataSourceUpdateMode = DataSourceUpdateMode.Never;            
    validationPairs = new List<ValidationTypeMessagePair>();
  }

  public void AddValidationPair(Validator.ValidationType validationType, string validationMessage)
  {
    validationPairs.Add(new ValidationTypeMessagePair(validationType, validationMessage));
  }

  public bool Validate()
  {
    foreach (ValidationTypeMessagePair validationPair in validationPairs)
    {
      if (!Validator.Validate(validationPair.ValidationType, textBox, Messages.Localize(validationPair.ValidationMessage))) return false;
    }
    textBox.DataBindings["Text"].WriteValue();
    return true;
  }

  public void ClearValidationStatus()
  {
    textBox.BackColor = System.Drawing.SystemColors.Window;
  }

}

有趣的方法 - 你是如何在包装器中实现这些验证方法的?我也遇到了第三方控件(Resco DetailView)的这个问题,不知道是否可以应用相同的技术。你是从这些控件继承而来的吗?你是否成功保留了设计时支持? - Michał Drozdowicz
谢谢你的代码 - 我以前从没见过DataBindings[string].WriteValue。根据我的回答,我不需要遵循你的方法,但如果我需要强制绑定数据,你的回答会非常有帮助。 - Michał Drozdowicz

0

我认为,为了通过聚焦其他控件来触发验证和验证完成事件,您需要将表单的AutoValidate属性设置为AutoValidate.EnableAllowFocusChange。

希望能有所帮助。=]


0

如果有人觉得有用,我会描述一下我应用的解决方法。

在OK处理程序中,我添加了代码,将焦点放在包含要验证的控件的面板上。当数据编辑控件失去焦点时,它会触发验证和已验证事件,并将数据绑定回模型类。这样,表单(顺便说一句,它是通用于“向导”的许多部分,并且只知道屏幕加载到哪个面板上)可以强制验证控件。

有点像黑客技巧,但现在可以使用。


我更新了我的答案,并附上了代码示例。正如我之前所说,我尝试使用焦点事件来验证表单。然而,我没有成功。紧凑框架中没有简单的方法来验证表单这一事实相当奇怪。 - empi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接