C# C“最佳方式”;“验证”;绑定到窗体的对象

C# C“最佳方式”;“验证”;绑定到窗体的对象,c#,winforms,forms,validation,C#,Winforms,Forms,Validation,我得到了一个绑定到表单的业务对象(每个属性绑定到一个控件)。存在一些业务规范(例如此字段不应为空,此字段必须大于0等)。检查所有规则的最佳方法是什么 我目前在每个控件上都有一个验证器,所以我可以检查所有验证器是否正常,但我真的不喜欢这个解决方案。事实上,这些规则是有争议的,很难同时看到所有的规则 我可以有一个大的方法CheckValidaty来检查所有的规则,但这会导致与验证器的双重检查 您会怎么做,其他解决方案?验证器方法有什么问题?这是完全可以接受的,您可以编写自己的,以实现自己的规则。验证

我得到了一个绑定到表单的业务对象(每个属性绑定到一个控件)。存在一些业务规范(例如此字段不应为空,此字段必须大于0等)。检查所有规则的最佳方法是什么

我目前在每个控件上都有一个验证器,所以我可以检查所有验证器是否正常,但我真的不喜欢这个解决方案。事实上,这些规则是有争议的,很难同时看到所有的规则

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


您会怎么做,其他解决方案?

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

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

有两种验证:特定于数据的验证(在持久性层)和用户界面验证。我更喜欢将验证放在输入端附近,因为通常您希望向用户显示错误,并且尝试将数据验证连接到用户界面会添加更多必须与数据绑定间接匹配的间接

将数据验证放在控制类中似乎不是一个好主意。这基本上意味着控件类只能用于一个特定字段

Windows窗体的标准做法是将数据验证放入容器中。这样,验证可以对照其他属性的状态进行检查,并将特定控件连接到ErrorProvider对象,以显示相关的错误消息

class EmployeeForm:UserControl
{
雇员对象雇员;
// ...
无效employeeNameTextBox\u正在验证(对象发送方,CancelEventArgs e)
{
if(employee.Name.Trim().Length==0){
errorProvider.SetError(employeeNameTextBox,“员工必须有姓名”);
e、 取消=真;
}
}
无效employeeHireDateControl_验证(…)
{
如果(employee.HireDate
标准的WF方法是在控件失去焦点或在容器(或容器的容器)上调用ValidateChildren时,为特定控件触发验证事件。通过容器上控件的事件属性为该事件设置处理程序;处理程序将自动添加到容器中

我不知道为什么这种方式对您不起作用,除非您不喜欢默认的拒绝放弃关注错误的行为,您可以通过将容器(或容器的容器)的AutoValidate属性设置为EnableAllowFocusChange来更改这种行为


具体告诉我们您不喜欢标准Windows窗体方式的哪些方面,也许我们可以提供替代方案,或者说服您使用标准方式来做您想做的事情

有两种验证:特定于数据的验证(在持久层中)和用户界面验证。我更喜欢将验证放在输入端附近,因为通常您希望向用户显示错误,并且尝试将数据验证连接到用户界面会添加更多必须与数据绑定间接匹配的间接

将数据验证放在控制类中似乎不是一个好主意。这基本上意味着控件类只能用于一个特定字段

Windows窗体的标准做法是将数据验证放入容器中。这样,验证可以对照其他属性的状态进行检查,并将特定控件连接到ErrorProvider对象,以显示相关的错误消息

class EmployeeForm:UserControl
{
雇员对象雇员;
// ...
无效employeeNameTextBox\u正在验证(对象发送方,CancelEventArgs e)
{
if(employee.Name.Trim().Length==0){
errorProvider.SetError(employeeNameTextBox,“员工必须有姓名”);
e、 取消=真;
}
}
无效employeeHireDateControl_验证(…)
{
如果(employee.HireDate
标准的WF方法是在控件失去焦点或在容器(或容器的容器)上调用ValidateChildren时,为特定控件触发验证事件。通过容器上控件的事件属性为该事件设置处理程序;处理程序将自动添加到容器中

我不知道为什么这种方式对您不起作用,除非您不喜欢默认的拒绝放弃关注错误的行为,您可以通过将容器(或容器的容器)的AutoValidate属性设置为EnableAllowFocusChange来更改这种行为

具体告诉我们您不喜欢标准Windows窗体方式的哪些方面,也许我们可以提供其他方式或pe 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; } } }
   - 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
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