2009-08-28 55 views
1

我得到了一个绑定到表单的业务对象(每个属性绑定到一个控件)。有一些业务特定的比率(例如这个字段不应该是空的,这个字段必须大于0等)。检查所有规则的最佳方法是什么?C#验证绑定到表单的对象的最佳方法

我目前在每个控制器上都有一个验证器,所以我可以检查所有验证器是否可以,但我不太喜欢这个解决方案。事实上,这些规则是分散的,并不容易一次全部看到。

我可以有一个很大的方法CheckValidaty检查所有的规则,但这导致与验证器双重检查。

你会做什么,其他解决方案?

+0

WPF或的WinForms? – 2009-08-28 08:40:24

回答

0

验证方法有什么问题?这是完全可以接受的,你可以自己写,实现你自己的规则。

+0

Inf act我有自定义使用控件和验证器在控件内部,所以我将规则声明为验证器属性(例如:valueCanBeNull = true)。但是这种方法不会强调规则。同事找到一个特定的规则和所有规则并不容易。 – Toto 2009-08-28 08:43:41

3

有两种验证:数据特定验证(在持久层)和用户界面验证。我更喜欢在输入端附近进行验证,因为通常情况下,您想向用户展示哪些问题,并尝试将数据验证连接到用户界面,从而增加了更多的必须与数据绑定间接匹配的间接方向。

把控制类中的数据验证看起来不是一个好主意。这基本上意味着控制类只能用于一个特定的领域。

标准的Windows Forms处事方式是将数据验证放入容器。这样,验证可以检查其他属性的状态,并将特定控件连接到ErrorProvider对象以显示相关的错误消息。

class EmployeeForm : UserControl 
{ 
    EmployeeObject employee; 

    // ... 

    void employeeNameTextBox_Validating (object sender, CancelEventArgs e) 
    { 
     if (employee.Name.Trim().Length == 0) { 
      errorProvider.SetError (employeeNameTextBox, "Employee must have a name"); 
      e.Cancel = true; 
     } 
    } 

    void employeeHireDateControl_Validating (...) 
    { 
     if (employee.HireDate < employee.BirthDate) { 
      errorProvider.SetError (employeeHireDateControl, 
       "Employee hire date must be after birth date"); 
      e.Cancel = true; 
     } 
    } 
} 

class ExplorerStyleInterface : ... 
{ 
    // ... 

    bool TryDisplayNewForm (Form oldForm, Form newForm) 
    { 
     if (! oldForm.ValidateChildren()) 
      return false; 

     else { 
      HideForm (oldForm); 
      ShowForm (newForm); 
      return true; 
     } 
    } 
}

标准WF方法是,当控件失去焦点或发射的具体控制的验证事件时ValidateChildren被称为容器(或容器的容器)。您通过容器控件的事件属性为此事件设置处理程序;处理程序会自动添加到容器中。

我不知道为什么这种方式不适合你,除非你不喜欢拒绝重点关注错误的默认行为,你可以通过设置容器的AutoValidate属性来改变它(或者容器的容器)改为EnableAllowFocusChange。

具体告诉我们您不喜欢标准Windows Forms做事方式,也许我们可以提供替代方案或说服您以标准方式做你想做的事。

+0

我喜欢这种方法。要深入了解这一点。如果其他人想要拥有东西,请不要回答大量时间。 – Toto 2009-08-28 11:44:31

1

如果你有这样的情况:

- Many controls in the Winform to 
    validate 
    - A validation rule for each control 
    - You want an overall validation within the Save() command 
    - You don't want validation when controls focus changes 
    - You also need an red icon showing errors in each control 

然后你就可以复制并粘贴下面的代码,它实现了带有2个文本框和一个保存按钮的窗体:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ValidationApp 
{ 
    public class ValidationTestForm : Form 
    { 
     private TextBox textBox1; 
     private TextBox textBox2; 
     private Button btnSave; 
     private ErrorProvider errorProvider1; 

      /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.components = new System.ComponentModel.Container(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      this.textBox2 = new System.Windows.Forms.TextBox(); 
      this.btnSave = new System.Windows.Forms.Button(); 
      this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components); 
      ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit(); 
      this.SuspendLayout(); 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(131, 28); 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(100, 20); 
      this.textBox1.TabIndex = 0; 
      // 
      // textBox2 
      // 
      this.textBox2.Location = new System.Drawing.Point(131, 65); 
      this.textBox2.Name = "textBox2"; 
      this.textBox2.Size = new System.Drawing.Size(100, 20); 
      this.textBox2.TabIndex = 1; 
      // 
      // btnSave 
      // 
      this.btnSave.Location = new System.Drawing.Point(76, 102); 
      this.btnSave.Name = "btnSave"; 
      this.btnSave.Size = new System.Drawing.Size(95, 30); 
      this.btnSave.TabIndex = 2; 
      this.btnSave.Text = "Save"; 
      this.btnSave.UseVisualStyleBackColor = true; 
      this.btnSave.Click += new System.EventHandler(this.btnSave_Click); 
      // 
      // errorProvider1 
      // 
      this.errorProvider1.ContainerControl = this; 
      // 
      // ValidationTestForm 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(266, 144); 
      this.Controls.Add(this.btnSave); 
      this.Controls.Add(this.textBox2); 
      this.Controls.Add(this.textBox1); 
      this.Name = "ValidationTestForm"; 
      this.Text = "ValidationTestForm"; 
      ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit(); 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     public ValidationTestForm() 
     { 
      InitializeComponent(); 

      // path validation 
      this.AutoValidate = AutoValidate.Disable; // validation to happen only when you call ValidateChildren, not when change focus 
      this.textBox1.CausesValidation = true; 
      this.textBox2.CausesValidation = true; 
      textBox1.Validating += new System.ComponentModel.CancelEventHandler(textBox1_Validating); 
      textBox2.Validating += new System.ComponentModel.CancelEventHandler(textBox2_Validating); 

     } 

     private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) 
     { 
      if (textBox1.Text.Length == 0) 
      { 
       e.Cancel = true; 
       errorProvider1.SetError(this.textBox1, "A value is required."); 
      } 
      else 
      { 
       e.Cancel = false; 
       this.errorProvider1.SetError(this.textBox1, ""); 
      } 
     } 

     private void textBox2_Validating(object sender, System.ComponentModel.CancelEventArgs e) 
     { 
      if (textBox2.Text.Length == 0) 
      { 
       e.Cancel = true; 
       errorProvider1.SetError(this.textBox2, "A value is required."); 
      } 
      else 
      { 
       e.Cancel = false; 
       this.errorProvider1.SetError(this.textBox2, ""); 
      } 
     } 



     private void btnSave_Click(object sender, EventArgs e) 
     { 
      if (this.ValidateChildren()) //will examine all the children of the current control, causing the Validating event to occur on a control 
      { 
       // Validated! - Do something then 
      } 

     } 
    } 
} 

注:

textBox1_Validating, textBox2_Validating...do the rule check 
相关问题