我得到了一个绑定到表单的业务对象(每个属性绑定到一个控件)。有一些业务特定的比率(例如这个字段不应该是空的,这个字段必须大于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