C# 无法获取实现类的属性
我有一个行为,它接受displayname属性,并在自动生成数据网格时设置其列标题。当网格绑定到一个特定类型的集合时,我可以正常工作。如果我有某个基类的集合,它将不起作用,尽管如果我不使用我的行为,它从基类自动生成派生类的列不会有问题 当集合类型是基类时,找到的唯一属性是来自基类的属性,我希望能够显示来自实现集合的属性 想法 问题是:C# 无法获取实现类的属性,c#,.net,wpf,C#,.net,Wpf,我有一个行为,它接受displayname属性,并在自动生成数据网格时设置其列标题。当网格绑定到一个特定类型的集合时,我可以正常工作。如果我有某个基类的集合,它将不起作用,尽管如果我不使用我的行为,它从基类自动生成派生类的列不会有问题 当集合类型是基类时,找到的唯一属性是来自基类的属性,我希望能够显示来自实现集合的属性 想法 问题是: DataGridAutoGeneratingColumnEventArgs.PropertyDescriptor提供集合的声明值类型的属性信息,而不是实际的项类型
DataGridAutoGeneratingColumnEventArgs.PropertyDescriptor
提供集合的声明值类型的属性信息,而不是实际的项类型
行为准则:
#region Setup
/// <summary>
/// Called when [attached].
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.AutoGeneratingColumn += HandleAutoGeneratingColumns;
}
/// <summary>
/// Called when [detaching].
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.AutoGeneratingColumn -= HandleAutoGeneratingColumns;
}
#endregion
#region Helpers
/// <summary>
/// Handles the automatic generating columns.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="dataGridAutoGeneratingColumnEventArgs">The <see cref="DataGridAutoGeneratingColumnEventArgs"/> instance containing the event data.</param>
private void HandleAutoGeneratingColumns(object sender, DataGridAutoGeneratingColumnEventArgs dataGridAutoGeneratingColumnEventArgs)
{
if (AssociatedObject != null)
{
var displayName = GetPropertyDisplayName(dataGridAutoGeneratingColumnEventArgs.PropertyDescriptor);
if (!string.IsNullOrEmpty(displayName))
{
dataGridAutoGeneratingColumnEventArgs.Column.Header = displayName;
dataGridAutoGeneratingColumnEventArgs.Column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
}
else
{
dataGridAutoGeneratingColumnEventArgs.Column.Visibility = Visibility.Collapsed;
}
}
}
/// <summary>
/// Gets the display name of the property.
/// </summary>
/// <param name="descriptor">The descriptor.</param>
/// <returns></returns>
[CanBeNull]
private static string GetPropertyDisplayName(object descriptor)
{
string returnValue = null;
var propertyDescriptor = descriptor as PropertyDescriptor;
if (propertyDescriptor != null)
{
var displayName = propertyDescriptor.Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
if (displayName != null && !Equals(displayName, DisplayNameAttribute.Default))
{
returnValue = displayName.DisplayName;
}
}
else
{
var propertyInfo = descriptor as PropertyInfo;
if (propertyInfo != null)
{
var attributes = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
foreach (var attribute in attributes)
{
var displayName = attribute as DisplayNameAttribute;
if (displayName != null && !Equals(displayName, DisplayNameAttribute.Default))
{
returnValue = displayName.DisplayName;
}
}
}
}
return returnValue;
}
#区域设置
///
///在[附加]时调用。
///
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.AutoGeneratingColumn+=HandleAutoGeneratingColumns;
}
///
///在[分离]时调用。
///
附加时受保护的覆盖无效()
{
base.OnDetaching();
AssociatedObject.AutoGeneratingColumn-=HandleAutoGeneratingColumns;
}
#端区
#地区助手
///
///处理自动生成列。
///
///发送者。
///包含事件数据的实例。
私有void HandleAutoGeneratingColumns(对象发送方、DataGridAutoGeneratingColumnEventArgs DataGridAutoGeneratingColumnEventArgs)
{
if(AssociatedObject!=null)
{
var displayName=GetPropertyDisplayName(dataGridAutoGeneratingColumnEventArgs.PropertyDescriptor);
如果(!string.IsNullOrEmpty(displayName))
{
dataGridAutoGeneratingColumnEventArgs.Column.Header=displayName;
dataGridAutoGeneratingColumnEventArgs.Column.Width=新的DataGridLength(1,DataGridLengthUnitType.Star);
}
其他的
{
dataGridAutoGeneratingColumnEventArgs.Column.Visibility=可见性。已折叠;
}
}
}
///
///获取属性的显示名称。
///
///描述符。
///
[CanBeNull]
私有静态字符串GetPropertyDisplayName(对象描述符)
{
字符串returnValue=null;
var propertyDescriptor=作为propertyDescriptor的描述符;
if(propertyDescriptor!=null)
{
变量displayName=propertyDescriptor.Attributes[typeof(DisplayNameAttribute)]作为DisplayNameAttribute;
if(displayName!=null&&!等于(displayName,DisplayNameAttribute.Default))
{
returnValue=displayName.displayName;
}
}
其他的
{
var propertyInfo=描述符为propertyInfo;
if(propertyInfo!=null)
{
var attributes=propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute),true);
foreach(属性中的var属性)
{
var displayName=作为displayName属性的属性;
if(displayName!=null&&!等于(displayName,DisplayNameAttribute.Default))
{
returnValue=displayName.displayName;
}
}
}
}
返回值;
}
来自一个绑定属性的示例
public class DefaultMatchedItems : ILookupItem
{
#region Properties
/// <summary>
/// Gets or sets the first column value.
/// </summary>
[DisplayName("Long Name")]
[CanBeNull]
public string FirstColumnValue { get; set; }
/// <summary>
/// Gets or sets the second column value.
/// </summary>
[DisplayName("Short Name")]
[CanBeNull]
public string SecondColumnValue { get; set; }
/// <summary>
/// Gets or sets the third column value.
/// </summary>
[DisplayName("Abbreviation")]
[CanBeNull]
public string ThirdColumnValue { get; set; }
/// <summary>
/// Gets or sets the identifier.
/// </summary>
[Browsable(false)]
[NotNull]
public string Identifier { get; set; }
public interface ILookupItem
{
/// <summary>
/// Determines whether [contains] [the specified value].
/// </summary>
/// <param name="value">The value.</param>
/// <param name="ignoreCase">if set to <c>true</c> [ignore case].</param>
/// <returns>
/// <c>true</c> if [contains] [the specified value]; otherwise, <c>false</c>.
/// </returns>
bool Contains(string value, bool ignoreCase = true);
/// <summary>
/// Gets the display value.
/// </summary>
/// <param name="identifier">The identifier.</param>
/// <returns>The first non blank section of the matching value</returns>
string GetDisplayValue(string identifier);
}
公共类DefaultMatchedItems:ILookupItem
{
#区域属性
///
///获取或设置第一列值。
///
[显示名称(“长名称”)]
[CanBeNull]
公共字符串FirstColumnValue{get;set;}
///
///获取或设置第二列值。
///
[显示名称(“短名称”)]
[CanBeNull]
公共字符串SecondColumnValue{get;set;}
///
///获取或设置第三列的值。
///
[显示名称(“缩写”)]
[CanBeNull]
公共字符串ThirdColumnValue{get;set;}
///
///获取或设置标识符。
///
[可浏览(错误)]
[非空]
公共字符串标识符{get;set;}
公共接口ILookupItem
{
///
///确定[是否包含][指定的值]。
///
///价值。
///如果设置为true[忽略大小写]。
///
///如果[包含][指定值],则为true;否则为false。
///
bool Contains(字符串值,bool ignoreCase=true);
///
///获取显示值。
///
///标识符。
///匹配值的第一个非空部分
字符串GetDisplayValue(字符串标识符);
}
DataGridAutoGeneratingColumnEventArgs.PropertyDescriptor
为您提供绑定到AssociatedObject.ItemsSource的集合的声明项类型的属性信息
如果我绑定一个类型为ObservableCollection
(当然也可以是List
)的集合,并用ItemSub
的实例填充它,我可以使用以下类重新创建它
public class ItemBase
{
[DisplayName("Base Foo")]
public virtual String Foo { get; set; }
[DisplayName("All Bar")]
public virtual String Bar { get; set; }
}
public class ItemSub : Item
{
[DisplayName("Sub Foo")]
public override String Foo { get; set; }
}
对于Foo
,e.PropertyDescriptor.DisplayName
是“基本Foo”
如果我将集合类型更改为ObservableCollection
(仅用于测试目的--object
的集合通常不是好的实践),e.PropertyDescriptor.DisplayName
是“Sub Foo”。如果我随后将集合中第一个项的类型更改为itembease
,我将得到“Base Foo”
因此,您最好的做法可能是从事件参数中获取属性名称,但请转到AssociatedObject.Items
以获取集合中实际项的运行时类型,并使用该类型的属性。DataGridAutoGeneratingColumnEventArgs.PropertyDescriptor
将为您提供声明项的属性信息集合的项目类型