使用 DefaultCellStyle 加速 DataGridView 单元格内容居中
Speeding up DataGridView Cell Content Centering Using DefaultCellStyle
似乎在 DataGridView 中调用基于列的分配来居中所有单元格的内容非常慢。例如,使用下面的代码是相当慢的:
For j As Integer = 0 To UBound(columnheaders) - 1
datagridview1.Columns(j).SortMode = DataGridViewColumnSortMode.Automatic
datagridview1.Columns(j).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
Next
如果上面的代码被注释掉,DataGridView 加载速度会更快,但单元格条目不会居中。因此,有没有更快的解决方法?
所以我深入挖掘了 .Net 参考源,我 95% 确定您的问题是 DefaultCellStyle 是一项昂贵的操作。如果您的所有列都将具有完全相同的 CellStyle,请尝试为第一列抓取一次,然后对其余列进行分配。
仅供参考,这是 DataGridViewColumn 使用的 DefaultCellStyle 属性:
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/DataGridViewBand.cs,f93400c6fe8a705f
public virtual DataGridViewCellStyle DefaultCellStyle
{
get
{
DataGridViewCellStyle dgvcs = (DataGridViewCellStyle)this.Properties.GetObject(PropDefaultCellStyle);
if (dgvcs == null)
{
dgvcs = new DataGridViewCellStyle();
dgvcs.AddScope(this.DataGridView,
this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
this.Properties.SetObject(PropDefaultCellStyle, dgvcs);
}
return dgvcs;
}
set
{
DataGridViewCellStyle dgvcs = null;
if (this.HasDefaultCellStyle)
{
dgvcs = this.DefaultCellStyle;
dgvcs.RemoveScope(this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
}
if (value != null || this.Properties.ContainsObject(PropDefaultCellStyle))
{
if (value != null)
{
value.AddScope(this.DataGridView,
this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
}
this.Properties.SetObject(PropDefaultCellStyle, value);
}
if (((dgvcs != null && value == null) ||
(dgvcs == null && value != null) ||
(dgvcs != null && value != null && !dgvcs.Equals(this.DefaultCellStyle))) && this.DataGridView != null)
{
this.DataGridView.OnBandDefaultCellStyleChanged(this);
}
}
}
如您所见,获取/设置 DefaultCellStyle 的逻辑很复杂。
顺便说一句,您是如何构建 DataGridView 的?如果您使用的是 Visual Studio 表单设计器,则有一种方法可以设置诸如所有列都将直接继承的 DefaultCellStyle 之类的东西,或者直接在设计器中的各个列上设置 CellStyle - 以及排序模式,这顺便说一句,我可能是错的,但我认为 'Automatic' 是默认的排序模式。
我发现似乎是一步解决方案,它使用一行语法将居中分配给整个 DataGridView:
C#:
dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
VB.NET
dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
处理时间也比许多论坛帖子描述的循环遍历每一列要短得多。最初,我确实注意到在几个帖子中提到了 RowsDefaultCellStyle
命令,但是没有使用或提供 .Alignment
属性。
我也在定义 DGV 后立即设置了上述命令,如:
Dim datagridview1 As New DataGridView
datagridview1.Visible = False
datagridview1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
datagridview1.AutoGenerateColumns = True
在从 DT 获取数据之前调用列居中。
似乎在 DataGridView 中调用基于列的分配来居中所有单元格的内容非常慢。例如,使用下面的代码是相当慢的:
For j As Integer = 0 To UBound(columnheaders) - 1
datagridview1.Columns(j).SortMode = DataGridViewColumnSortMode.Automatic
datagridview1.Columns(j).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
Next
如果上面的代码被注释掉,DataGridView 加载速度会更快,但单元格条目不会居中。因此,有没有更快的解决方法?
所以我深入挖掘了 .Net 参考源,我 95% 确定您的问题是 DefaultCellStyle 是一项昂贵的操作。如果您的所有列都将具有完全相同的 CellStyle,请尝试为第一列抓取一次,然后对其余列进行分配。
仅供参考,这是 DataGridViewColumn 使用的 DefaultCellStyle 属性: https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/DataGridViewBand.cs,f93400c6fe8a705f
public virtual DataGridViewCellStyle DefaultCellStyle
{
get
{
DataGridViewCellStyle dgvcs = (DataGridViewCellStyle)this.Properties.GetObject(PropDefaultCellStyle);
if (dgvcs == null)
{
dgvcs = new DataGridViewCellStyle();
dgvcs.AddScope(this.DataGridView,
this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
this.Properties.SetObject(PropDefaultCellStyle, dgvcs);
}
return dgvcs;
}
set
{
DataGridViewCellStyle dgvcs = null;
if (this.HasDefaultCellStyle)
{
dgvcs = this.DefaultCellStyle;
dgvcs.RemoveScope(this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
}
if (value != null || this.Properties.ContainsObject(PropDefaultCellStyle))
{
if (value != null)
{
value.AddScope(this.DataGridView,
this.bandIsRow ? DataGridViewCellStyleScopes.Row : DataGridViewCellStyleScopes.Column);
}
this.Properties.SetObject(PropDefaultCellStyle, value);
}
if (((dgvcs != null && value == null) ||
(dgvcs == null && value != null) ||
(dgvcs != null && value != null && !dgvcs.Equals(this.DefaultCellStyle))) && this.DataGridView != null)
{
this.DataGridView.OnBandDefaultCellStyleChanged(this);
}
}
}
如您所见,获取/设置 DefaultCellStyle 的逻辑很复杂。
顺便说一句,您是如何构建 DataGridView 的?如果您使用的是 Visual Studio 表单设计器,则有一种方法可以设置诸如所有列都将直接继承的 DefaultCellStyle 之类的东西,或者直接在设计器中的各个列上设置 CellStyle - 以及排序模式,这顺便说一句,我可能是错的,但我认为 'Automatic' 是默认的排序模式。
我发现似乎是一步解决方案,它使用一行语法将居中分配给整个 DataGridView:
C#:
dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
VB.NET
dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
处理时间也比许多论坛帖子描述的循环遍历每一列要短得多。最初,我确实注意到在几个帖子中提到了 RowsDefaultCellStyle
命令,但是没有使用或提供 .Alignment
属性。
我也在定义 DGV 后立即设置了上述命令,如:
Dim datagridview1 As New DataGridView
datagridview1.Visible = False
datagridview1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
datagridview1.AutoGenerateColumns = True
在从 DT 获取数据之前调用列居中。