我正在制作一个TextBox,就像它可以存储一个空值一样。为了做到这一点,我有一个变量NullMode,表明存储的值是Null,并在TextChanged我将其设置为false,并在特定的用户操作我将其设置为true和Text为一个值,表明有文本框内的null。然后,基于NullMode,文本框的绘制方式不同。
现在,我有一个类似信号量的方法,以防止事件句柄在我不需要时触发。以下是它的外观:
private void input_TextChanged(object sender, EventArgs e)
{
if (_preventTextBoxEvents)
return;
_preventTextBoxEvents = true;
//if (NullMode)
// Text = "";
NullMode = false;
ValidateInput();
_preventTextBoxEvents = false;
}
现在,如果我需要将文本框文本设置为应该在nullmode中显示的内容,我只需在执行true之前设置_preventTextBoxEvents,它就可以正常工作。
BUT!当用户尝试在文本框中输入内容时,我还需要删除文本!所以我需要将Text设置为“”。问题是,如果我取消注释,表单在事件处理程序退出后关闭。我无法阻止它(在FormClosing中e.Cancel = true没有帮助!)并且不明白可能导致它的原因。也没有错误消息(我没有做try-catch)。
我的逻辑,当我做Text =“”时。应该触发OnTextChanged,它应该调用我的TextChanged,它会看到_preventTextBoxEvents为true并退出,因此不会有堆栈溢出/无限递归。
发生了什么事?
答案 0 :(得分:3)
应该如此(假设您的文本框名为input
)
if (NullMode)
input.Text = "";
单独的文本是指当前的表单标题,而不是input.Text属性 但是,请允许我说您的方法很危险。如果由于某种原因,您的ValidateInput抛出异常,您将退出事件处理程序而不将global _preventTextBoxEvents恢复为false;
添加try - catch - finally
private void input_TextChanged(object sender, EventArgs e)
{
if (_preventTextBoxEvents)
return;
_preventTextBoxEvents = true;
try
{
if (NullMode) input.Text = "";
NullMode = false;
ValidateInput();
}
catch(Exception ex)
{
// Inform user of the exception occurred inside your ValidateInput
MessageBox.Show(ex.Message);
}
finally
{
// Be sure to restore this global to a functioning value.
_preventTextBoxEvents = false;
}
}
此外,您可以删除 _preventTextBoxEvents 的逻辑,只需在程序输入事件代码时断开TextChanged事件:
try
{
input.TextChanged -= new EventArgs(input_TextChanged);
// Now, the input textbox is no more connected to this code, you
// could happily change the textbox text without worry to reenter in this code
}
...
finally
{
// Work finished, reconnect this code to the event TextChanged
input.TextChanged += new EventArgs(input_TextChanged);
}