我想更好地了解验证如何在Windows窗体应用程序中工作。互联网充满了微不足道的例子,但我找不到一个解释控制验证的非平凡例子。无论如何,感谢SwDevMan81和Hans Passant我从一个比昨天好得多的地方开始。如何在Windows窗体应用程序中实现控件验证?
“真正的应用程序”包含许多TextBox控件的对话框。每个控件都实现了Validating事件。正如您在示例中看到的,由于Click事件导致将验证事件发送到每个控件,因此调用ValidateChildren。该应用程序还使用ErrorProvider控件来提供用户反馈。昨天,我不明白如何使用确定按钮Click事件来执行此验证。今天,我的对话按预期工作。单击确定按钮会导致ErrorProvider执行控件无效并且对话框未意外关闭的事情。
所以,虽然这似乎工作,我仍然觉得,我“在线外”着色。在Windows Forms应用程序中是否有用于控制验证的“最佳实践”文档/网站?
在仍然令我困惑的许多事情中,当Ok按钮DialogResult属性设置为返回DialogResult.OK时,我无法找到对话框行为的解释。为什么设置这个属性会影响验证? (尝试我的例子,有没有这条线,看看我的意思。)
我昨天的问题(它会出现)大部分来自不理解ValidateChildren方法,并从我设置Ok按钮DialogResult属性为DialogResult。好。将该属性设置为DialogResult.None似乎改变了Form类的一些自动行为。
TIA
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dialog dialog = new Dialog();
if(dialog.ShowDialog() == DialogResult.OK)
Console.Beep();
}
}
public class Dialog : Form
{
TextBox m_TextBox0;
TextBox m_TextBox1; // not validated
TextBox m_TextBox2;
Button m_OkBtn;
Button m_CancelBtn;
ErrorProvider m_ErrorProvider;
public Dialog()
{
m_TextBox0 = CreateTextBox(0, "TextBox 0");
m_TextBox1 = CreateTextBox(1, "TextBox 1");
m_TextBox2 = CreateTextBox(2, "TextBox 2");
m_OkBtn = CreateButton(3, "Ok");
m_CancelBtn = CreateButton(4, "Cancel");
m_ErrorProvider = new ErrorProvider(this);
//m_BtnOk.DialogResult = DialogResult.OK;
m_OkBtn.Click += new EventHandler(BtnOk_Click);
m_OkBtn.CausesValidation = true;
m_CancelBtn.DialogResult = DialogResult.Cancel;
m_CancelBtn.CausesValidation = false;
}
void BtnOk_Click(object sender, EventArgs e)
{
if(ValidateChildren())
{
DialogResult = DialogResult.OK;
Close();
}
}
void TextBox_Validating(object sender, CancelEventArgs e)
{
m_ErrorProvider.Clear();
TextBox textBox = sender as TextBox;
// m_TextBox1 is always valid, the others are valid if they have text.
bool valid = textBox.TabIndex == 1 || textBox.Text.Length > 0;
if(!valid)
m_ErrorProvider.SetError(textBox, "Error " + textBox.Name);
e.Cancel = !valid;
}
Button CreateButton(int index, string name)
{
Button button = new Button();
button.TabIndex = index;
button.Text = name;
button.Location = new System.Drawing.Point(0, index * 30);
Controls.Add(button);
return button;
}
TextBox CreateTextBox(int index, string name)
{
Label label = new Label();
label.Text = name;
label.Location = new System.Drawing.Point(0, index * 30);
TextBox textBox = new TextBox();
textBox.TabIndex = index;
textBox.CausesValidation = true;
textBox.Validating += new CancelEventHandler(TextBox_Validating);
textBox.Location = new System.Drawing.Point(100, index * 30);
Controls.Add(label);
Controls.Add(textBox);
return textBox;
}
}
}
编辑:这里是最终的解决方案。我认为它很容易使用,同时也满足所有其他要求。我提前道歉这个问题结束了多久。如果我能向你展示所有真正的应用程序,那么为什么这么重要会更有意义。无论如何,感谢帮助这只老狗学习了一个新的技巧。
答案是为每个控制需要验证一个ErrorProvider控件(对整个对话一个ErrorProvider控件。在此之后,这一切是相当简单的。
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dialog dialog = new Dialog();
if(dialog.ShowDialog() == DialogResult.OK)
Console.Beep();
}
}
public class CompositeControl
{
Label m_Label;
TextBox m_TextBox;
ErrorProvider m_ErrorProvider;
Dialog m_Dialog;
public CompositeControl(int index, string name, Dialog dialog)
{
m_Label = new Label();
m_Label.Text = name;
m_Label.Location = new System.Drawing.Point(0, index * 30);
m_TextBox = new TextBox();
m_TextBox.TabIndex = index;
m_TextBox.CausesValidation = true;
m_TextBox.Validating += new CancelEventHandler(TextBox_Validating);
m_TextBox.Location = new System.Drawing.Point(100, index * 30);
m_Dialog = dialog;
m_ErrorProvider = new ErrorProvider(m_Dialog);
m_Dialog.Controls.Add(m_Label);
m_Dialog.Controls.Add(m_TextBox);
}
void TextBox_Validating(object sender, CancelEventArgs e)
{
TextBox textBox = sender as TextBox;
if(!m_Dialog.IsClosing && textBox.Text.Length == 0)
return;
// m_TextBox1 is always valid, the others are valid if they have text.
bool valid = textBox.TabIndex == 1 || textBox.Text.Length > 0;
if(!valid)
m_ErrorProvider.SetError(textBox, "Error " + textBox.Name);
else
m_ErrorProvider.Clear();
e.Cancel = !valid;
}
}
public class Dialog : Form
{
CompositeControl m_CompositeControl0;
CompositeControl m_CompositeControl1; // not validated
CompositeControl m_CompositeControl2;
Button m_OkBtn;
Button m_CancelBtn;
bool m_IsClosing = false;
public Dialog()
{
m_CompositeControl0 = new CompositeControl(0, "TextBox 0", this);
m_CompositeControl1 = new CompositeControl(1, "TextBox 1", this);
m_CompositeControl2 = new CompositeControl(2, "TextBox 2", this);
m_OkBtn = CreateButton(3, "Ok");
m_CancelBtn = CreateButton(4, "Cancel");
//m_BtnOk.DialogResult = DialogResult.OK;
m_OkBtn.Click += new EventHandler(BtnOk_Click);
m_OkBtn.CausesValidation = true;
m_CancelBtn.DialogResult = DialogResult.Cancel;
m_CancelBtn.CausesValidation = false;
}
void BtnOk_Click(object sender, EventArgs e)
{
m_IsClosing = true;
if(ValidateChildren())
{
DialogResult = DialogResult.OK;
Close();
}
m_IsClosing = false;
}
Button CreateButton(int index, string name)
{
Button button = new Button();
button.TabIndex = index;
button.Text = name;
button.Location = new System.Drawing.Point(0, index * 30);
Controls.Add(button);
return button;
}
public bool IsClosing { get { return m_IsClosing; } }
}
}
这个问题是一个跟进one我昨天问。
先生们,谢谢你的帮助。 – 2011-03-28 19:48:03
到e.Cancel分配真实并不总是防止焦点变化,特别是如果Form.Autovalidate == EnableAllowFocusChange。如果你想给操作者自由在其中为了修复他的错误,点击确定之前,像滚动的是有助于修复该错误眼帘 – 2017-09-12 14:06:29