更改Windows Form中ErrorProvider图标时抛出StackOverflowException异常
问题根因分析
你遇到的System.StackOverflowException和自定义ErrorProvider图标没有关联,是textBox1_Leave事件的处理逻辑触发了无限死循环导致的:
当textBox1失去焦点时触发Leave事件,你在事件逻辑中调用了textBox1.Focus()强制将焦点切回该控件,这个操作会再次触发textBox1的Leave事件,无限循环下最终触发栈溢出,报错出现在SetError行只是代码执行顺序的巧合,和图标资源无关。
解决方案
方案1(推荐):改用专门的输入验证事件
WinForm提供了Validating事件专门用于控件输入校验,不需要手动控制焦点即可实现校验不通过禁止失去焦点的效果,代码示例如下:
private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if(string.IsNullOrEmpty(textBox1.Text)) { e.Cancel = true; // 校验不通过,禁止控件失去焦点 errorProvider1.Icon = Properties.Resources.cross; errorProvider1.SetError(this.textBox1, "请输入用户ID"); } else { errorProvider1.Icon = Properties.Resources.right; errorProvider1.SetError(this.textBox1, string.Empty); // 校验通过清除错误提示 } }
使用该方案需要确认textBox1的CausesValidation属性为true(默认值即为true)。
方案2:给Leave事件加防重复触发标志
如果你需要保留Leave事件的处理逻辑,可以新增一个标志位避免循环触发:
// 全局标志位 private bool _isLeaveProcessing = false; private void textBox1_Leave(object sender, EventArgs e) { if (_isLeaveProcessing) return; _isLeaveProcessing = true; try { if(string.IsNullOrEmpty(textBox1.Text)) { textBox1.Focus(); errorProvider1.Icon = Properties.Resources.cross; errorProvider1.SetError(this.textBox1, "请输入用户ID"); } else { errorProvider1.Icon = Properties.Resources.right; errorProvider1.SetError(this.textBox1, string.Empty); } } finally { _isLeaveProcessing = false; } }
验证方法
你可以先注释掉代码里的textBox1.Focus()行再运行,程序不会抛出异常即可确认你的图标资源引入操作是正确的。
内容的提问来源于stack exchange,提问作者Mahin
相关产品推荐
相关产品推荐

