2009-08-28 102 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 
相關問題