使用代码从ViewModel绑定控件中检索System.ComponentModel.DataAnnotations.DisplayAttribute属性

时间:2010-03-08 00:33:40

标签: c# .net wpf silverlight-3.0

我注意到SL3 Validators在创建验证消息时会自动使用DisplayAttribute中的属性。我对如何使用代码从控件绑定中提取此信息的任何建议感兴趣。我举了一个例子:

ViewModel代码:

[Display(Name="First Name")]
public string FirstName { get; set; }

我知道可以在Control-by-Control的基础上实现这一点,如下所示(在本例中为TextBox):

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;

我很感兴趣,如果有任何方法可以做到这一点,而不需要知道具体的控制类型。

提前感谢任何想法!!

1 个答案:

答案 0 :(得分:1)

好问题。不幸的是,虽然你可以硬编码一些属性并且非常安全,但实际上没有办法一般地做到这一点。例如,ContentControl.ContentProperty,TextBlock.TextProperty,TextBox.TextProperty等。

Silverlight中的DataForm也做同样的事情。我还重新实现了一个名为GetPropertyByPath的简单助手方法。它基本上做了你的代码所做的事情,除了它可以走多步属性路径。它无法访问索引属性,但DataForm也无法访问索引属性。

从那时起,获取DisplayAttribute正如您所示。

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;

}