在运行时在Windows窗体上找到ErrorProvider

我正在制作一个扩展方法库,以便在Windows窗体应用程序中使用。 我打算创建的方法之一将使输入控件上的错误状态设置更容易,例如

public static void SetError(this System.Windows.Forms.TextBox textBox, string errorMessage) { if (string.IsNullOrEmpty(errorMessage)) { //reset control state textBox.BackColor = System.Drawing.SystemColors.WindowText; } else { //set background colour to a nice shade of red textBox.BackColor = System.Drawing.Color.MistyRose; } //try to locate an ErrorProvider on the control's containing form. var errorProvider = LocateErrorProvider(textBox); if (errorProvider != null) { //set error message on error provider (or clear it) errorProvider.SetError(textBox, errorMessage); } } 

我试图弄清楚LocateErrorProvider方法。 我想要做的是检查我的表单上是否存在ErrorProvider,然后只有在它存在时才使用它。

ErrorProvider是一个Component而不是Control ,所以我无法通过form.Controls属性获取它。 我已经尝试将父表单转换为各种对象,但无济于事。

更新 :我已设法使用以下代码使用reflection到达ErrorProvider:

 private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) { //get the containing form of the control var form = control.GetContainerControl(); //use reflection to get to "components" field var componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (componentField != null) { //get the component collection from field var components = componentField.GetValue(form); //locate the ErrorProvider within the collection return (components as System.ComponentModel.IContainer).Components.OfType().FirstOrDefault(); } else { return null; } } 

就个人而言,我不太喜欢使用硬编码的字段名称来到现场。 但在这种情况下它似乎工作得很好。 有没有人有更好的方法来达到同样的效果?

到目前为止,这似乎解决了我的问题:

 private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) { //get the containing form of the control var form = control.GetContainerControl(); //use reflection to get to "components" field var componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (componentField != null) { //get the component collection from field var components = componentField.GetValue(form); //locate the ErrorProvider within the collection return (components as System.ComponentModel.IContainer).Components.OfType().FirstOrDefault(); } else { return null; } } 

感谢Hans&Cody的出色创意。

这就是接口的设计目的。 他们强制执行一个类来实现行为。 您需要的行为是表单具有ErrorProvider。 所以写一个这样的界面:

 public interface IHasErrorProvider { ErrorProvider Provider { get; } } 

并让表单与错误提供程序实现接口:

 public partial class Form1 : Form, IHasErrorProvider { public ErrorProvider Provider { get { return errorProvider1; } } // etc.. } 

现在检索错误提供程序很简单:

  private static ErrorProvider GetErrorProvider(Control control) { var impl = control.FindForm() as IHasErrorProvider; return impl != null ? impl.Provider : null; } 

在VS2005这工作:

  private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) { try { //get the containing form of the control System.Windows.Forms.IContainerControl form = control.GetContainerControl(); //use reflection to get to "components" field System.Reflection.FieldInfo componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (componentField != null) { //get the component collection from field object components = componentField.GetValue(form); object oReturn = null; //locate the ErrorProvider within the collection foreach (object o in ((System.ComponentModel.Container)components).Components) { if (o.GetType() == typeof(System.Windows.Forms.ErrorProvider)) { oReturn = o; break; } } return (ErrorProvider)oReturn; } } catch { return null; } return null; }