在运行时在 Windows 窗体上定位 ErrorProvider

tob*_*s86 3 .net c# winforms

我正在制作一个在 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试找出LocateErrorProvider方法。我想要做的是检查我的表单上是否存在 ErrorProvider,然后仅在它存在时才使用它。

ErrorProvider 是 aComponent而不是 a Control,所以我无法通过form.Controls属性访问它。我尝试将父表单转换为各种对象,但无济于事。

更新:我已经设法使用以下代码使用反射到达 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<System.Windows.Forms.ErrorProvider>().FirstOrDefault();
    }
    else
    {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

tob*_*s86 5

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

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<System.Windows.Forms.ErrorProvider>().FirstOrDefault();
    }
    else
    {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢 Hans & Cody 的优秀创意。