DataGrid.AutoGenerateColumns 的智能行为






4.87/5 (21投票s)
使用AutoGenerateColumns生成按需数据列。
引言
当您使用 DateGrid
控件来填充表格数据时,DataGrid.AutoGenerateColumns
属性提供了一种方便的方法来动态生成数据列。 然而,DataGrid
实际上会显示所有具有属性名称的属性,而不是标题名称。 如果您能够控制列的生成,这将很有帮助。 本文提出了一种解决方案,可以在充分利用 DataGrid.AutoGenerateColumns
优势的同时,轻松指定标题信息。
Using the Code
该解决方案引入了一个智能的 Behavior
对象,该对象插入到 DateGrid
中,以便自动生成在数据项的属性中指定的标题信息。 在数据项中,
- 您可以指定要为每个列标题显示的
字符串
- 您可以指定一个空白标题;并且
- 您可以轻松决定显示或隐藏哪些列
使用 Behavior
对象需要三个步骤。
- 添加
System.Windows.Interactivity
的引用,并将 SmartColumnBehavior.cs 添加到项目中。 - 使用属性在数据项的属性中指定标题。 如果您不想显示该属性,请不要添加该属性。 这是一个“带属性”的数据项的自解释示例。
public class DataItem { // Don't create this column public int Id { get; set; } // Blank header [DisplayName(" ")] public bool AddToBag { get; set; } [DisplayName("Theme Name")] public string ThemeName { get; set; } }
- 在 XAML 文件中,如下插入
Behavior
对象<Window ... xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:local="clr-namespace:AttributtedDataColumn" /> <DataGrid ItemsSource="{Binding DataItems}" > <i:Interaction.Behaviors> <local:SmartColumnBehavior /> </i:Interaction.Behaviors> </DataGrid>
现在,您可以编译并运行了!
幕后
如果您将 DataGrid.AutoGenerateColumns
属性设置为 true
,DataGrid.AutoGeneratingColumn
事件将为您提供一个机会,在列生成过程中操作数据列。 有许多方法可以实现事件处理程序。 我选择将其封装在一个 Behavior
对象中,以使其可插拔和可重用。 当附加到 DataGrid
控件时,它为 DataGrid
提供了额外的行为。 在此实现中,事件处理程序中的逻辑检测数据项属性的属性,并返回用于生成列和标题信息的信息。 此外,如果您需要更多功能,例如图标、过滤器等,您可以将您的扩展添加到 Behavior
对象。 以下是 Behavior
的源代码。
public class ColumnHeaderBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
AssociatedObject.AutoGeneratingColumn +=
new EventHandler<DataGridAutoGeneratingColumnEventArgs>(OnAutoGeneratingColumn);
}
protected override void OnDetaching()
{
AssociatedObject.AutoGeneratingColumn -=
new EventHandler<DataGridAutoGeneratingColumnEventArgs>(OnAutoGeneratingColumn);
}
protected void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
string displayName = GetPropertyDisplayName(e.PropertyDescriptor);
if (!string.IsNullOrEmpty(displayName))
{
e.Column.Header = displayName;
}
else
{
e.Cancel = true;
}
}
protected static string GetPropertyDisplayName(object descriptor)
{
PropertyDescriptor pd = descriptor as PropertyDescriptor;
if (pd != null)
{
DisplayNameAttribute attr = pd.Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
if ((attr != null) && (attr != DisplayNameAttribute.Default))
{
return attr.DisplayName;
}
}
else
{
PropertyInfo pi = descriptor as PropertyInfo;
if (pi != null)
{
Object[] attrs = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true);
foreach (var att in attrs)
{
DisplayNameAttribute attribute = att as DisplayNameAttribute;
if ((attribute != null) && (attribute != DisplayNameAttribute.Default))
{
return attribute.DisplayName;
}
}
}
}
return null;
}
}
Behavior
类是一个泛型类,用于为控件附加附加行为。 在示例中,控件类型是 DataGrid
。 因此,我从 Behavior
派生了 SmartColumnBehavior
类OnAttached()
方法。 该类封装了列生成逻辑,并将附加到 XAML 中的 DataGrid
。 当 DataGrid
生成数据列时,将为每个数据列触发 DataGrid.AutoGeneratingColumn
事件。 这是处理自定义列生成的地方。 在 Behavior
对象中,我订阅了 AutoGeneratingColumn
事件,并检测了标题显示名称。 对于数据项中的每个属性,如果我可以在属性中找到显示名称,我会将其分配给 e.Column.Header
中的列标题。 如果我找不到该属性,我将通过将 e.Cancel
设置为 true
来取消列生成。 e.Column
属性包含许多用于自定义列生成的属性。 以上只是一个简单的实现。