65.9K
CodeProject 正在变化。 阅读更多。
Home

DataGrid.AutoGenerateColumns 的智能行为

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (21投票s)

2012年5月23日

CPOL

3分钟阅读

viewsIcon

55311

downloadIcon

1124

使用AutoGenerateColumns生成按需数据列。

引言

当您使用 DateGrid 控件来填充表格数据时,DataGrid.AutoGenerateColumns 属性提供了一种方便的方法来动态生成数据列。 然而,DataGrid 实际上会显示所有具有属性名称的属性,而不是标题名称。 如果您能够控制列的生成,这将很有帮助。 本文提出了一种解决方案,可以在充分利用 DataGrid.AutoGenerateColumns 优势的同时,轻松指定标题信息。

Using the Code

该解决方案引入了一个智能的 Behavior 对象,该对象插入到 DateGrid 中,以便自动生成在数据项的属性中指定的标题信息。 在数据项中,

  1. 您可以指定要为每个列标题显示的 字符串
  2. 您可以指定一个空白标题;并且
  3. 您可以轻松决定显示或隐藏哪些列

使用 Behavior 对象需要三个步骤。

  1. 添加 System.Windows.Interactivity 的引用,并将 SmartColumnBehavior.cs 添加到项目中。
  2. 使用属性在数据项的属性中指定标题。 如果您不想显示该属性,请不要添加该属性。 这是一个“带属性”的数据项的自解释示例。
    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; }
    } 
  3. 在 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 属性设置为 trueDataGrid.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 属性包含许多用于自定义列生成的属性。 以上只是一个简单的实现。

© . All rights reserved.