ToolTip 不是 Control,它是 Component,因此您不会在 Form 的 Controls 集合中找到它。
它是 System.ComponentModel.IContainer components 私有字段的一部分,通常在分部类的表单设计器部分中定义。
要查找某个控件的ToolTip,可以使用ToolTip.GetToolTip([Control])方法,然后验证返回的字符串是否为空。
如果您可以访问表单的 components 字段 - 即,从包含要验证的控件的表单调用 ValidateText() 方法 - 您可以将组件容器传递给该方法:
► 如果表单没有组件,container(在这两种方法中)将是null。
► 如果表单没有工具提示组件,var toolTip 将是null。
→ 保留object sender,然后转换为Control,因为在这里您只想访问公共属性,例如Text,它们属于公共Control 类。您不需要知道sender 的类型:Control 是所有控件的基本类型,并公开了所有公共属性。
bool result = ValidateText(this.someControl, this.components);
// [...]
public static bool ValidateText(object sender, IContainer container)
{
if (container == null) {
/* no components, decide what to do */
// [...]
}
var ctrl = sender as Control;
var toolTip = container.Components.OfType<ToolTip>()
.FirstOrDefault(tt => !string.IsNullOrEmpty(tt.GetToolTip(ctrl)));
if (toolTip != null) {
string tooltipText = toolTip.GetToolTip(ctrl);
// [...]
if (ctrl.Text == "") { }
return true;
}
return false;
}
否则,您可以通过反射访问组件集合,以防传递给 ValidateText() 方法的 Control 实例可能具有未确定的来源。
使用[form].GetType().GetField("components").GetValue([form]) as IContainer,我们可以访问components 字段值,然后像以前一样继续。
→ 这里,sender 已经属于 Control 类型,因为这是 sender 的真正性质。
→ ValidateText([Control]) 重载了之前的方法。当您为container 赋值后,您可以调用ValidateText(sender, container)。
bool result = ValidateText(someControl);
// [...]
using System.Reflection;
public static bool ValidateText(Control sender)
{
var flags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField;
Form form = sender.FindForm();
var container = form.GetType().GetField("components", flags).GetValue(form) as IContainer;
if (container == null) {
/* no components, decide what to do */
// [...]
}
// You can call ValidateText(sender, container) or continue
var toolTip = container.Components.OfType<ToolTip>()
.FirstOrDefault(tt => !string.IsNullOrEmpty(tt.GetToolTip(sender)));
if (toolTip != null) {
string tooltipText = toolTip.GetToolTip(sender);
// [...]
return true;
}
return false;
}