我得到了一個綁定到表單的業務對象(每個屬性綁定到一個控件)。有一些業務特定的比率(例如這個字段不應該是空的,這個字段必須大於0等)。檢查所有規則的最佳方法是什麼?C#驗證綁定到表單的對象的最佳方法
我目前在每個控制器上都有一個驗證器,所以我可以檢查所有驗證器是否可以,但我不太喜歡這個解決方案。事實上,這些規則是分散的,並不容易一次全部看到。
我可以有一個很大的方法CheckValidaty檢查所有的規則,但這導致與驗證器雙重檢查。
你會做什麼,其他解決方案?
我得到了一個綁定到表單的業務對象(每個屬性綁定到一個控件)。有一些業務特定的比率(例如這個字段不應該是空的,這個字段必須大於0等)。檢查所有規則的最佳方法是什麼?C#驗證綁定到表單的對象的最佳方法
我目前在每個控制器上都有一個驗證器,所以我可以檢查所有驗證器是否可以,但我不太喜歡這個解決方案。事實上,這些規則是分散的,並不容易一次全部看到。
我可以有一個很大的方法CheckValidaty檢查所有的規則,但這導致與驗證器雙重檢查。
你會做什麼,其他解決方案?
我建議讓BusinessObject實現IDataErrorInfo
。我認爲這是處理業務錯誤的最乾淨的方式。
在這些鏈接看看:
不錯!我比你更喜歡你的答案。看起來你可以混搭,如果你有特定於UI的錯誤。 – XXXXX 2009-08-30 08:51:01
驗證方法有什麼問題?這是完全可以接受的,你可以自己寫,實現你自己的規則。
Inf act我有自定義使用控件和驗證器在控件內部,所以我將規則聲明爲驗證器屬性(例如:valueCanBeNull = true)。但是這種方法不會強調規則。同事找到一個特定的規則和所有規則並不容易。 – Toto 2009-08-28 08:43:41
有兩種驗證:數據特定驗證(在持久層)和用戶界面驗證。我更喜歡在輸入端附近進行驗證,因爲通常情況下,您想向用戶展示哪些問題,並嘗試將數據驗證連接到用戶界面,從而增加了更多的必須與數據綁定間接匹配的間接方向。
把控制類中的數據驗證看起來不是一個好主意。這基本上意味着控制類只能用於一個特定的領域。
標準的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做事方式,也許我們可以提供替代方案或說服您以標準方式做你想做的事。
我喜歡這種方法。要深入瞭解這一點。如果其他人想要擁有東西,請不要回答大量時間。 – Toto 2009-08-28 11:44:31
如果你有這樣的情況:
- 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
WPF或的WinForms? – 2009-08-28 08:40:24