C# t进入WinForms库
每个C# t进入WinForms库,c#,.net,winforms,validation,user-interface,C#,.net,Winforms,Validation,User Interface,每个控件-派生对象都有两个名为验证和验证的事件。它还有一个名为的属性。当该值设置为true(默认为true)时,控件将参与验证。否则,它不会 验证是焦点的一部分。当您不关注控件时,将触发其验证事件。事实上,焦点事件是按特定顺序触发的。发件人: 当您使用 键盘(TAB、SHIFT+TAB等), 通过调用Select或 选择下一步控制方法,或按 设定 ContainerControl.:.ActiveControl 属性设置为当前窗体的焦点 事件按以下顺序发生: 进入 戈特福克斯 离开 验证 验证
控件
-派生对象都有两个名为验证
和验证
的事件。它还有一个名为的属性。当该值设置为true(默认为true)时,控件将参与验证。否则,它不会
验证是焦点的一部分。当您不关注控件时,将触发其验证事件。事实上,焦点事件是按特定顺序触发的。发件人:
当您使用
键盘(TAB、SHIFT+TAB等),
通过调用Select或
选择下一步控制方法,或按
设定
ContainerControl.:.ActiveControl
属性设置为当前窗体的焦点
事件按以下顺序发生:
此外,ContainerControl还有一个名为的方法,该方法将循环通过包含的控件,并验证它们。我意识到这个线程非常旧,但我想我会发布我提出的解决方案 WinForms上验证的最大问题是,只有在控件“失去焦点”时才执行验证。因此,用户必须实际在文本框内单击,然后单击其他地方,以执行验证例程。如果您只关心输入的数据是否正确,则可以这样做。但是,如果您试图确保用户没有跳过文本框而将文本框留空,那么这种方法就不能很好地工作 在我的解决方案中,当用户单击表单的submit按钮时,我检查表单上的每个控件(或指定的任何容器),并使用反射来确定是否为该控件定义了验证方法。如果是,则执行验证方法。如果任何验证失败,例程将返回失败并允许进程停止。此解决方案非常有效,尤其是当您需要验证多个表单时 1) 只需将这段代码复制并粘贴到您的项目中。我们正在使用反射,因此您需要在using语句中添加System.Reflection
class Validation
{
public static bool hasValidationErrors(System.Windows.Forms.Control.ControlCollection controls)
{
bool hasError = false;
// Now we need to loop through the controls and deterime if any of them have errors
foreach (Control control in controls)
{
// check the control and see what it returns
bool validControl = IsValid(control);
// If it's not valid then set the flag and keep going. We want to get through all
// the validators so they will display on the screen if errorProviders were used.
if (!validControl)
hasError = true;
// If its a container control then it may have children that need to be checked
if (control.HasChildren)
{
if (hasValidationErrors(control.Controls))
hasError = true;
}
}
return hasError;
}
// Here, let's determine if the control has a validating method attached to it
// and if it does, let's execute it and return the result
private static bool IsValid(object eventSource)
{
string name = "EventValidating";
Type targetType = eventSource.GetType();
do
{
FieldInfo[] fields = targetType.GetFields(
BindingFlags.Static |
BindingFlags.Instance |
BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.Name == name)
{
EventHandlerList eventHandlers = ((EventHandlerList)(eventSource.GetType().GetProperty("Events",
(BindingFlags.FlattenHierarchy |
(BindingFlags.NonPublic | BindingFlags.Instance))).GetValue(eventSource, null)));
Delegate d = eventHandlers[field.GetValue(eventSource)];
if ((!(d == null)))
{
Delegate[] subscribers = d.GetInvocationList();
// ok we found the validation event, let's get the event method and call it
foreach (Delegate d1 in subscribers)
{
// create the parameters
object sender = eventSource;
CancelEventArgs eventArgs = new CancelEventArgs();
eventArgs.Cancel = false;
object[] parameters = new object[2];
parameters[0] = sender;
parameters[1] = eventArgs;
// call the method
d1.DynamicInvoke(parameters);
// if the validation failed we need to return that failure
if (eventArgs.Cancel)
return false;
else
return true;
}
}
}
}
targetType = targetType.BaseType;
} while (targetType != null);
return true;
}
}
2) 对任何要验证的控件使用标准验证事件确认失败时,请务必使用e.取消强>
private void txtLastName_Validating(object sender, CancelEventArgs e)
{
if (txtLastName.Text.Trim() == String.Empty)
{
errorProvider1.SetError(txtLastName, "Last Name is Required");
e.Cancel = true;
}
else
errorProvider1.SetError(txtLastName, "");
}
3) 不要跳过这一步将表单上的自动验证属性设置为启用AllowFocusChange。这将允许在验证失败时切换到另一个控件
4) 最后,在Submit按钮方法中,调用Validation方法并指定要检查的容器。它可以是整个表单,也可以只是表单上的一个容器,如面板或组
private void btnSubmit_Click(object sender, EventArgs e)
{
// the controls collection can be the whole form or just a panel or group
if (Validation.hasValidationErrors(frmMain.Controls))
return;
// if we get here the validation passed
this.close();
}
快乐编码 如果将上述思想与通用验证事件处理程序相结合,您将获得一个良好的验证错误“框架”,其中包含业务类中的所有验证方法。我刚刚用丹麦的想法扩展了Bruce代码。 对实体框架和devexpress组件进行了测试,但是可以轻松删除这些依赖项。 享受吧
公共类验证管理器
{
///
///调用此方法以验证给定控件列表的所有控件
///验证事件将在每个事件上调用
///
///
///
公共静态bool hasvalidateErrors(System.Windows.Forms.Control.ControlCollection控件)
{
bool hasrerror=false;
//现在我们需要遍历控件并确定它们是否有错误
foreach(控件中的控件)
{
//检查控件并查看它返回的内容
bool validControl=IsValid(控制);
//如果无效,则设置标志并继续。我们希望通过所有测试
//如果使用了errorProviders,验证程序将显示在屏幕上。
如果(!validControl)
hasrerror=true;
//如果它是一个容器控件,那么它可能有需要检查的子项
if(control.HasChildren)
{
if(HasValidationErrors(control.Controls))
hasrerror=true;
}
}
返回错误;
}
///
///将所有正在验证的事件附加到此事件处理程序(如果控件需要验证)
///将在绑定的业务实体上搜索名为Validate+PropertyName的方法,如果找到,则调用该方法
///如果在方法逻辑中检测到验证错误,则引发包含所需消息的异常
///
///
///
公共静态void ValidationHandler(对象发送方,CancelEventArgs e)
{
BaseEdit控件=发送方为BaseEdit;
如果(control.DataBindings.Count>0)//控件已绑定
{
string bindedFieldName=control.DataBindings[0].BindingMemberInfo.BindingField;
object BindeObject=control.BindingManager.Current;
如果(bindeObject!=null)//控件绑定到对象实例
{
//查找并调用name=Validate+PropertyName的方法
MethodInfo validationMethod=(来自bindeObject.GetType().GetMethods()中的方法)
其中method.IsPublic&&
method.Name==String.Format(“验证{0}”,bindedFieldName)&&
class Validation
{
public static bool hasValidationErrors(System.Windows.Forms.Control.ControlCollection controls)
{
bool hasError = false;
// Now we need to loop through the controls and deterime if any of them have errors
foreach (Control control in controls)
{
// check the control and see what it returns
bool validControl = IsValid(control);
// If it's not valid then set the flag and keep going. We want to get through all
// the validators so they will display on the screen if errorProviders were used.
if (!validControl)
hasError = true;
// If its a container control then it may have children that need to be checked
if (control.HasChildren)
{
if (hasValidationErrors(control.Controls))
hasError = true;
}
}
return hasError;
}
// Here, let's determine if the control has a validating method attached to it
// and if it does, let's execute it and return the result
private static bool IsValid(object eventSource)
{
string name = "EventValidating";
Type targetType = eventSource.GetType();
do
{
FieldInfo[] fields = targetType.GetFields(
BindingFlags.Static |
BindingFlags.Instance |
BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.Name == name)
{
EventHandlerList eventHandlers = ((EventHandlerList)(eventSource.GetType().GetProperty("Events",
(BindingFlags.FlattenHierarchy |
(BindingFlags.NonPublic | BindingFlags.Instance))).GetValue(eventSource, null)));
Delegate d = eventHandlers[field.GetValue(eventSource)];
if ((!(d == null)))
{
Delegate[] subscribers = d.GetInvocationList();
// ok we found the validation event, let's get the event method and call it
foreach (Delegate d1 in subscribers)
{
// create the parameters
object sender = eventSource;
CancelEventArgs eventArgs = new CancelEventArgs();
eventArgs.Cancel = false;
object[] parameters = new object[2];
parameters[0] = sender;
parameters[1] = eventArgs;
// call the method
d1.DynamicInvoke(parameters);
// if the validation failed we need to return that failure
if (eventArgs.Cancel)
return false;
else
return true;
}
}
}
}
targetType = targetType.BaseType;
} while (targetType != null);
return true;
}
}
private void txtLastName_Validating(object sender, CancelEventArgs e)
{
if (txtLastName.Text.Trim() == String.Empty)
{
errorProvider1.SetError(txtLastName, "Last Name is Required");
e.Cancel = true;
}
else
errorProvider1.SetError(txtLastName, "");
}
private void btnSubmit_Click(object sender, EventArgs e)
{
// the controls collection can be the whole form or just a panel or group
if (Validation.hasValidationErrors(frmMain.Controls))
return;
// if we get here the validation passed
this.close();
}