【问题标题】:How to determine if Control has Text property如何确定控件是否具有文本属性
【发布时间】:2013-02-20 14:26:04
【问题描述】:

当我在表单上迭代一堆不同的控件时,而不是尝试访问 Text 属性:

String text = String.Empty;
foreach(Control control in this.Controls)
{
   try
   {
      text = control.Text;
   }
   catch(Exception exception)
   {
      // This control probably doesn't have the Text property.
      Debug.WriteLine(exception.Message);
   }
}

有没有办法确定给定控件是否具有 Text 属性?像这样的:

String text = String.Empty;
foreach(Control control in this.Controls)
{
   if(control has Text property)
   {
      text = control.Text;
   }
}

我绝对鄙视 Try/Catch 块(当然,除非没有更好的选择)。

【问题讨论】:

  • 您可以使用反射,但是否只需要特定类型的控件?你可以做if (control is TextBox || control is Label)
  • 是的,我有很多自定义控件,有些没有 Text 属性,有些有。此外,您在 VS 的工具箱中看到的任何(标准)控件都是(或可能是 - 取决于用户正在创建的内容)在表单上。虽然我可以使用您的方法,但仍有许多其他标准控件具有 Text 属性 - 如果它们有,我将需要它。 :-)
  • 从 Control 派生的任何对象都有一个名为 Text 的属性。
  • @JasonVoorhees 从Control 派生的所有对象都具有Text 属性。如果他们没有,您的代码将无法编译。但是,该属性隐藏在不支持它的控件的设计器中。即使您的自定义控件没有覆盖 Text 属性,它仍然存在。
  • @JasonVoorhees System.Windows.Forms.MainMenu 不继承自 Control。我以为你在谈论 Control 实例。

标签: c# .net winforms xaml


【解决方案1】:

所有Control 对象都有一个Text property,因此使用反射来确定它是没有意义的。它将始终返回true

您的问题实际上是某些控件从其Text 属性中抛出异常,因为它们不支持它。

如果您还希望能够使用事先不知道的自定义控件,则应坚持当前的解决方案并捕获异常。但是,您应该捕获抛出的特定异常,例如NotSupportedException

如果您只遇到事先知道的控件,则可以选择您知道具有有效Text 属性的控件。例如:

public static bool HasWorkingTextProperty(Control control)
{
    return control is Label
        || control is TextBox
        || control is ComboBox;
}

var controlsWithText = from c in this.Controls
                       where HasWorkingTextProperty(c)
                       select c;

foreach(var control in controlsWithText)
{
    string text = control.Text;
    // Do something with it.
}

如果您实现自己的自定义控件,这些控件可能有也可能没有Text 属性,那么您可以从指示这一点的基类派生它们:

public abstract class CustomControlBase : Control
{
    public virtual bool HasText
    {
        get { return false; }
    }
}

public class MyCustomControl : CustomControlBase
{
    public override bool HasText
    {
        get { return true; }
    }

    public override string Text
    {
        get { /* Do something. */ }
        set { /* Do something. */ }
    }
}

public static bool HasWorkingTextProperty(Control control)
{
    return (control is CustomControlBase && ((CustomControlBase)control).HasText)
        || control is Label
        || control is TextBox
        || control is ComboBox;
}

【讨论】:

  • 非常感谢@Virtlink - 很好的解决方案。
【解决方案2】:

您的问题是如何确定 Control 是否具有 Text 属性,因此您可以使用 Reflection 来做到这一点:

control.GetType().GetProperties().Any(x => x.Name == "Text");

编辑:如果您查看Control 类,您会看到它有一个Text 属性。

现在,如果某些覆盖Control 类的自定义控件在访问Text 属性时抛出异常,它违反了Liskov substitution principle。在这种情况下,我建议您确定这些控件,尽管您所做的似乎没问题。

【讨论】:

  • 不错的解决方案!,我喜欢它。 :)
【解决方案3】:

看看这个:

private void Form1_Load(object sender, EventArgs e)
{
     foreach (Control ctrl in this.Controls)
     {
          PropertyInfo[] properties = ctrl.GetType().GetProperties();
          foreach(PropertyInfo pi in properties)
              if (pi.Name == "Text")
              { 
                    //has text
              }
       }

}

【讨论】:

  • 这不能解决他的问题:所有控件都有一个 Text 属性。但是,有些抛出异常...
猜你喜欢
  • 2018-12-12
  • 2011-03-04
  • 2011-09-12
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多