我想更好地瞭解驗證如何在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