Retrieve System.ComponentModel.DataAnnotations.DisplayAttribute properties from ViewModel-bound Controls using code
I've noticed that the SL3 Validators automatically uses the properties from DisplayAttribute when creating validation messages. I'm interested in any suggestions on how to extract this information from a control's binding using code. I've included an example:
ViewModel code:
[Display(Name="First Name")]
public string FirstName { get; set; }
I know ca开发者_运维技巧n achieve this on a Control-by-Control basis doing something like the following (TextBox in this case):
BindingExpression dataExpression = _firstNameTextBox.GetBindingExpression(TextBox.TextProperty)
Type dataType = dataExpression.DataItem.GetType();
PropertyInfo propInfo = dataType.GetProperty(dataExpression.ParentBinding.Path.Path);
DisplayAttribute attr = propInfo.GetCustomAttributes(false).OfType<DisplayAttribute>().FirstOrDefault();
return (attr == null) ? dataExpression.ParentBinding.Path.Path : attr.Name;
I'm interested if there's any way to do this generically, without needing to know the specific type of Control.
Thanks in advance for any thoughts!!
Good question. Unfortunately there's really no way to generically do it though you can hard code a few properties and be pretty safe. For example, ContentControl.ContentProperty, TextBlock.TextProperty, TextBox.TextProperty, etc.
DataForm in Silverlight does the same thing. I also re-implemented a simple helper method they use called GetPropertyByPath. It basically does what your code does except it can walk a multi-step property path. It can't access indexed properties but neither can DataForm so it's at least as good as that.
From that point on, getting at the DisplayAttribute is just as you've shown.
public static PropertyInfo GetPropertyByPath( object obj, string propertyPath )
{
ParameterValidation.ThrowIfNullOrWhitespace( propertyPath, "propertyPath" );
if ( obj == null ) {
return null;
} // if
Type type = obj.GetType( );
PropertyInfo propertyInfo = null;
foreach ( var part in propertyPath.Split( new char[] { '.' } ) ) {
// On subsequent iterations use the type of the property
if ( propertyInfo != null ) {
type = propertyInfo.PropertyType;
} // if
// Get the property at this part
propertyInfo = type.GetProperty( part );
// Not found
if ( propertyInfo == null ) {
return null;
} // if
// Can't navigate into indexer
if ( propertyInfo.GetIndexParameters( ).Length > 0 ) {
return null;
} // if
} // foreach
return propertyInfo;
}
精彩评论