当数据绑定到IEnumerable <something>?</something>时,网格视图如何确定列

时间:2015-04-03 15:24:17

标签: c# asp.net gridview

在尝试使用SharePoint时,我创建了一个简单的Web部件,用于显示分区及其各自的大小。这是相关代码:

ASCX文件:

[...]
<asp:GridView ID="diskSpaceReport" runat="server" DataSource="<%# Partitions %>">
    <Columns>
        <asp:BoundField DataField="Name" HeaderText="Name" />
        <asp:BoundField DataField="Used" HeaderText="Used" />
    </Columns>
</asp:GridView>

代码隐藏:

protected IEnumerable<Partition> Partitions
{
    get
    {
        Contract.Ensures(Contract.Result<IEnumerable<Partition>>() != null);

        return from drive in DriveInfo.GetDrives()
               let usedSpace = drive.IsReady ?
                   drive.TotalFreeSpace * 100 / drive.TotalSize : 0
               select new Partition(drive.Name, usedSpace);
    }
}

Partition.cs:

[...]
public string Name { get { ... } }
public Percentage Used { get { ... } }
[...]

这是该类的唯一两个属性

问题

网格视图显示三列:

  • 名称,
  • 使用的空间百分比,
  • 这个名字,再一次。

为了隐藏第三列,我必须将AutoGenerateColumns="false"添加到<asp:GridView>块。如果我删除<Columns>块,网格视图只显示一个列 - 名称(以前是第三列)。

问题

我不明白网格视图如何自动生成列。我认为当网格视图绑定到SQL表或类似的数据元素时它很有效,但是当绑定到自定义对象的枚举时它显然会失败。

如何找到Name属性,但却未能理解应显示Used

1 个答案:

答案 0 :(得分:2)

您可以检查默认自动列生成器here的源代码。

在快速阅读中看起来PublicInstance propertiesIsBindableType返回true。 IsBindableType来源可用here。它包括基本类型(int,string,date等),以及标有BindableAttribute的类型。

确定是否生成列的源代码的关键位是这一位:

            if (type.IsPrimitive ||
                   (type == typeof(string)) ||
                   (type == typeof(DateTime)) ||
                   (type == typeof(Decimal)) ||
                   (type == typeof(Guid)) ||
                // support for new SqlServer 2008 types:
                   (type == typeof(DateTimeOffset)) ||
                   (type == typeof(TimeSpan))) {
                return true;
            }
            else {
                BindableTypeAttribute bindableTypeAttribute = (BindableTypeAttribute)TypeDescriptor.GetAttributes(type)[typeof(BindableTypeAttribute)];
                if (bindableTypeAttribute != null) {
                    return bindableTypeAttribute.IsBindable;
                }
                else {
                    //We consider enums as Bindable types by default but provide an opt-out mechanism using BindableTypeAttribute. (Ex : EntityState)
                    //So the order of above if-else block is important.
                    return (enableEnums && type.IsEnum);
                }
            }