问题
When I iterate over a bunch of different controls on a Form, instead of trying to access the Text property:
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);
}
}
Is there a way to just determine whether or not a given control has a Text property? Something like this:
String text = String.Empty;
foreach(Control control in this.Controls)
{
if(control has Text property)
{
text = control.Text;
}
}
I absolutely despise the Try/Catch blocks (unless there is no better alternative, of-course).
回答1:
All Control
objects have a Text property, so there is no point in using reflection to determine that. It will always return true
.
Your problem actually is that some controls throw an exception from their Text
property because they don't support it.
If you also want to be able to use custom controls that you don't know in advance, you should stick to your current solution and catch the exceptions. However, you should catch the specific exception thrown, for example NotSupportedException
.
If you only ever encounter controls that you know in advance, you can select the controls that you know have a working Text
property. For example:
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.
}
And if you implement your own custom controls that may or may not have a Text
property, then you can derive them from a base class that indicates this:
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;
}
回答2:
Your question is How to determine if Control has Text property, so here is how you can do it using Reflection:
control.GetType().GetProperties().Any(x => x.Name == "Text");
Edit: If you take a look at the Control
class, you will see it has a Text
property.
Now, if some custom control that overrides the Control
class throws an exception when accessing to the Text
property, it is violating the Liskov substitution principle. In that case, I suggest you identifying those controls, although what you're doing seems to be fine.
回答3:
Check this out:
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
}
}
}
来源:https://stackoverflow.com/questions/15236462/how-to-determine-if-control-has-text-property