我正在制作一个在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
属性访问它。我已经尝试将父表单转换为各种对象,但无济于事。
UPDATE :我已设法使用以下代码使用反射来访问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;
}
}
就个人而言,我不太喜欢使用硬编码的字段名称来到现场。但在这种情况下它似乎工作得很好。有没有人有更好的方法来获得相同的结果?
答案 0 :(得分:3)
到目前为止,这似乎解决了我的问题:
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;
}
}
感谢Hans&amp;科迪的出色创意。
答案 1 :(得分:1)
这就是设计接口的目的。他们强制执行一个类来实现行为。您需要的行为是表单具有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;
}
答案 2 :(得分:0)
可行:
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;
}