Ref*_*din 43 .net c# validation user-interface winforms
我需要在整个winform应用程序中实现输入验证.有许多不同的形式可以输入数据,我希望不通过表单控制来控制每个项目创建isValid等.别人怎么处理这个?
我看到大多数相关帖子都涉及Web应用程序和/或提及企业库验证应用程序块.现在我承认我还没有彻底研究过ELVAB,但对于我需要的东西来说似乎有些过分.我目前的想法是编写一个具有各种要求的类库,并将控件作为参数传递给它.我已经有了一个RegEx函数库,用于像isValidZipCode这样的东西,所以这可能是我开始的地方.
我想要的是一个验证按钮,onClick循环遍历该表单页面上的所有控件并执行所需的验证.我怎么能做到这一点?
Mat*_*ell 63
验证已内置到WinForms库中.
每个Control
派生的对象都有两个名为Validating
和的事件Validated
.它还有一个叫做的属性CausesValidation
.当此设置为true(默认情况下为true)时,控件将参与验证.否则,它没有.
验证作为焦点的一部分发生.当您关注控件时,会触发其验证事件.事实上,焦点事件是按特定顺序触发的.来自MSDN:
通过使用键盘(TAB,SHIFT + TAB等)更改焦点,通过调用Select或SelectNextControl方法,或通过将ContainerControl .. ::.ActiveControl属性设置为当前窗体,焦点事件发生在以下顺序:
- 输入
- 的GotFocus
- 离开
- 证实
- 验证
- 引发LostFocus
使用鼠标或通过调用Focus方法更改焦点时,焦点事件按以下顺序发生:
- 输入
- 的GotFocus
- 引发LostFocus
- 离开
- 证实
- 验证
如果CausesValidation属性设置为false,则抑制Validating和Validated事件.
如果在Validating事件委托中将CancelEventArgs的Cancel属性设置为true,则会禁止在Validating事件之后通常发生的所有事件.
此外,ContainerControl有一个方法ValidateChildren()
,它将循环包含的控件并验证它们.
Bru*_*uce 43
我意识到这个线程很老了,但我想我会发布我想出的解决方案.
在WinForms上验证的最大问题是验证仅在控件"失去焦点"时执行.因此,用户必须实际单击文本框内部,然后单击其他位置以执行验证例程.如果您只关心输入的数据是正确的,那么这很好.但是,如果您尝试确保用户没有通过跳过它而将文本框留空,那么这不会很好.
在我的解决方案中,当用户单击表单的提交按钮时,我检查表单上的每个控件(或指定的任何容器)并使用反射来确定是否为控件定义了验证方法.如果是,则执行验证方法.如果任何验证失败,则例程返回失败并允许该过程停止.如果您有多个表单需要验证,此解决方案效果很好.
1)只需将此部分代码复制并粘贴到您的项目中即可.我们正在使用Reflection,因此您需要将System.Reflection添加到using语句中
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;
}
}
Run Code Online (Sandbox Code Playgroud)
2)对要验证的任何控件使用标准验证事件. 当验证失败时,务必使用e.Cancel!
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, "");
}
Run Code Online (Sandbox Code Playgroud)
3)不要跳过这一步! 将窗体上的AutoValidate属性设置为EnableAllowFocusChange.即使验证失败,这也允许对另一个控件进行制表.
4)最后,在Submit Button方法中,调用Validation方法并指定要检查的容器.它可以是整个表单,也可以是表单上的容器,如Panel或Group.
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();
}
Run Code Online (Sandbox Code Playgroud)
快乐的编码!
在我自己的应用程序中,我需要在输入时验证尺寸.我使用的顺序如下
这种方法的优点是验证集中在给定形状程序的一个位置.我不必去修改每个控件,甚至不用担心窗体上不同类型的控件.当我设计软件时,我决定了UI如何用于文本框,列表框,组合框等.另外,不同级别的严重性处理方式也不同.
View负责指导表单通过接口做什么.它实际如何实现是由Form本身在它的Interface实现中处理的.视图不关心表单是否显示黄色表示警告,红色表示错误.只有它处理这两个级别.之后如果出现更好的显示警告与错误的想法,我可以在表单中进行更改,而不是使用View逻辑或Shape程序中的验证.
如果您正在考虑创建一个类来保存验证逻辑,那么您已经在那里了一半,这将使您在新设计中完成其余部分.
归档时间: |
|
查看次数: |
62201 次 |
最近记录: |