Mic*_*l J 3 c# events winforms
我试图更好地了解验证如何在Windows窗体应用程序中工作.互联网上充满了琐碎的例子,但我找不到一个解释控制验证的非平凡的例子.无论如何,多亏了SwDevMan81和Hans Passant,我从一个比昨天更好的地方开始.
"真正的应用程序"有一个包含许多TextBox控件的对话框.每个控件都实现Validating事件.正如您在示例中所看到的,ValidateChildren作为Click事件的结果被调用,导致Validating事件被发送到每个控件.该应用程序还使用ErrorProvider控件来提供用户反馈.昨天,我不明白如何使用Ok按钮Click事件来执行此验证.今天,我的对话框按预期工作.单击"确定"按钮会导致ErrorProvider执行控件无效且对话框未意外关闭的操作.
因此,虽然这似乎有效,但我感觉我"在线外".在Windows窗体应用程序中是否有用于控制验证的"最佳实践"文档/站点?
在许多令我困惑的事情中,当Ok按钮DialogResult属性设置为返回DialogResult.OK时,我无法找到对话框行为的解释.为什么设置此属性会干扰验证?(尝试使用和不使用该行的示例,看看我的意思.)
我昨天遇到的问题(看起来似乎)主要源于不了解ValidateChildren方法以及我将Ok按钮DialogResult属性设置为DialogResult.OK.将此属性设置为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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:这是最终的解决方案.我认为它很容易使用,同时也满足所有其他要求.我提前道歉这个问题到底有多长时间了.如果我可以向您展示所有真正的应用程序,那么为什么这么重要就更有意义了.无论如何,感谢帮助这只老狗学习新技巧.
答案是为每个需要验证的控件创建一个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; } }
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题是一个跟进一个我昨天问.
分配DialogResult属性是使对话框关闭的原因.它在设置时保持运行None.你不需要这个Close()电话.调用的代码ShowDialog()获取DialogResult您指定的值作为返回值.因此它知道对话框是否已关闭,或者是否已取消.
另请注意,您编写验证事件处理程序的方式,您不需要ValidateChildren().您设置e.Cancel = true为阻止用户远离文本框.这意味着当文本框被验证为正常时,她只能进入"确定"按钮.但是,您必须确保在显示对话框时首先选择具有验证的控件.
一个友好的对话框是用户可以在控件之间自由选项并选择"简单"的对话框.您现在需要两个验证,一个验证输入的值是否有效,另一个验证是否没有丢失值.您可以通过在Validation事件处理程序中接受空字符串来获得此结果.但Winforms不能很好地支持后者,你需要代码.
| 归档时间: |
|
| 查看次数: |
20837 次 |
| 最近记录: |