当数据绑定到 IEnumerable<Something> 时,网格视图如何确定列?
How does grid view determine the columns when data-bound to IEnumerable<Something>?
在试验 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 { ... } }
[...]
这是 class 的唯一两个属性。
问题
网格视图显示三列:
- 姓名,
- 使用的space百分比,
- 名字,再一次。
为了隐藏第三列,我必须将 AutoGenerateColumns="false"
添加到 <asp:GridView>
块。如果我删除 <Columns>
块,网格视图只显示一列——名称(以前是第三列)。
问题
我不明白网格视图如何自动生成列。我想当网格视图绑定到 SQL table 或类似的数据元素时效果很好,但当绑定到自定义对象的枚举时它显然会失败。
怎么找到Name
属性,但是没看懂Used
也要显示?
您可以检查默认自动列生成器的源代码 here。
快速浏览一下,Public
、Instance
properties
看起来 IsBindableType
returns 是正确的。
IsBindableType
来源可用 here。它包括原始类型(int、string、dates 等),以及标有 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);
}
}
在试验 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 { ... } }
[...]
这是 class 的唯一两个属性。
问题
网格视图显示三列:
- 姓名,
- 使用的space百分比,
- 名字,再一次。
为了隐藏第三列,我必须将 AutoGenerateColumns="false"
添加到 <asp:GridView>
块。如果我删除 <Columns>
块,网格视图只显示一列——名称(以前是第三列)。
问题
我不明白网格视图如何自动生成列。我想当网格视图绑定到 SQL table 或类似的数据元素时效果很好,但当绑定到自定义对象的枚举时它显然会失败。
怎么找到Name
属性,但是没看懂Used
也要显示?
您可以检查默认自动列生成器的源代码 here。
快速浏览一下,Public
、Instance
properties
看起来 IsBindableType
returns 是正确的。
IsBindableType
来源可用 here。它包括原始类型(int、string、dates 等),以及标有 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);
}
}