开发者

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;

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜