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).
For example the Text property of a Form is displayed in the title bar at the top of the form, is fairly small in character count, and usually displays the application or document name.
The name property changes to match any changes in the text property. E. The correct answer for your question is option (B)- They are the same when the control in first created.
The Text property is a string and can be used as an argument with the usual string-manipulation functions of Visual Basic. You can also manipulate it with the members of the String class. The following expression returns the number of characters in the TextBox1 control: Dim strLen As Integer = TextBox1.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With