下面的一些技巧是由 C1FlexGrid 论坛中总结来的一些常见问题。
技巧 1:请使用 BeginUpdate/EndUpdate 方法来提升性能
每次当一个单元格的值发生更改时,或多行、多列被添加或者从表格中删除,一些计算被执行用来重新计算表格的布局和更新显示。你可以通过调用
BeginUpdate 和 EndUpdate 方法封闭这些变化来显著提高性能。例如:
Visual Basic
' 在更新表格前调用 BeginUpdate。
flex.BeginUpdate()
' 做修改。
Try
Dim r As Integer = 0
Do While (r < _flex.Rows.Count)
Dim c As Integer = 0
Do While (c < _flex.Cols.Count)
_flex(r, c) = (r + c) c += 1 Loop r += 1
Loop
Finally
' 完成后调用 EndUpdate 。
_flex.EndUpdate()
End Try- C#
//在更新表格前调用 BeginUpdate。 _flex[r, c] = r + c;
|
注意,使用 try/finally 块来确保 C1FlexGridBase.EndUpdate 方法被调用,即使更新代码失败抛出异常。
注意:BeginUpdate 和 EndUpdate 方法在 C1FlexGrid 2010/v1 release 版本中添加。在之前的版本中,Redraw 属性被用来达到同样的目的。这种变化是用来
增加和其他控件使用 BeginUpdate 和 EndUpdate 模式的兼容性。
技巧 2:使用 AutoResize 属性来提升性能
当一个绑定的表格从一个数据源检索数据,它可以测量每个单元格,并设置列宽使它们适合所有的数据。这将确保表格的布局是显示数据源的最佳布局,但如果数据源很大时,它很耗费时间(如果超过上千行的话)。
基于这种情况,你应该将 AutoResize 属性设置为 False 并且使用代码来控制列宽。
注意:从 C1FlexGrid 2010/v1 release 版本开始,AutoResize 属性默认为
False。如果你的数据源有比较少的数据行数,并且你希望表格自动控制列宽的话,你可以将 AutoResize 属性设置为 True 或者在绑定、手动填充数据之后调用
AutoSizeCols 方法。这个改变适用于提高绑定大型数据源的性能。
技巧 3:基于单元格的值使用 DrawMode 属性动态指定单元格样式
表格允许你创建单元格样式并将它指定到行、列和任意单元格范围。你可以使用这个功能来根据单元格内容格式化单元格。例如,包含负值的单元格可以显示为红色。
你可以通过使用 SetCellStyle 方法来指定样式到单元格上做到这一点,但是在这个例子中,当单元格值发生变化时随时更新这个样式。同样的,如果表格绑定到数据源的话,在数据源发生重置时样式会丢失(如排序和过滤操作执行之后)。
在这种情况下,一个好的替代方案是使用表格的 OwnerDraw 功能来动态选择样式,当然是基于单元格的值。
例如,下面的代码展示了负值为红色,超过 1000 的为绿色:
Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' 使用随机值填充一列。
_flex.Cols(1).DataType = GetType(Integer)
Dim rnd As New Random
Dim r As Integer = 1
Do While (r < _flex.Rows.Count) _flex(r, 1) = rnd.Next(-10000, 10000) r += 1 Loop
' 创建一个样式来显示负值。
_flex.Styles.Add("Red").ForeColor = Color.Red
' 创建一个样式来显示值>= 1000。
_flex.Styles.Add("Green").ForeColor = Color.Green
' 通过设置 DrawMode 属性来允许 OwnerDraw。
_flex.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw End Sub
Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
' 检查行或者列包含整数数据。
If ((e.Row > 0) AndAlso (_flex.Cols(e.Col).DataType Is GetType(Integer))) Then
' 拿到将要绘制的单元格中的值。
Dim value As Integer = CInt(_flex(e.Row, e.Col)) If (value < 0) Then
' 如果单元格值< 0,使用 Red 样式。
e.Style = _flex.Styles("Red")
ElseIf (value >= 1000) Then
' 如果单元格值>= 1000,使用 Green 样式。
e.Style = _flex.Styles("Green")
End If
End If
End SubC#
private void Form1_Load(object sender, EventArgs e)
{
//使用随机值填充一列。
_flex.Cols[1].DataType = typeof(int); Random rnd = new Random();
for (int r = 1; r < _flex.Rows.Count; r++)
{
_flex[r, 1] = rnd.Next(-10000, 10000);
}
//创建一个样式来显示负值。
_flex.Styles.Add("Red").ForeColor = Color.Red;
//创建一个样式来显示值>= 1000。
_flex.Styles.Add("Green").ForeColor = Color.Green;
//通过设置 DrawMode 属性来允许 OwnerDraw。
_flex.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
_flex.OwnerDrawCell += new
C1.Win.C1FlexGrid.OwnerDrawCellEventHandler(_flex_OwnerDrawCell);
}
private void _flex_OwnerDrawCell(object sender,
C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
//检查行或者列包含整数数据。
if (e.Row > 0 && _flex.Cols[e.Col].DataType == typeof(int))
{
//拿到将要绘制的单元格中的值。
int value = (int)_flex[e.Row, e.Col]; if (value < 0)
{
//如果单元格值< 0,使用 Red 样式。
e.Style = _flex.Styles["Red"];
}
else if (value >= 1000)
{
//如果单元格值>= 1000,使用 Green 样式。
e.Style = _flex.Styles["Green"];
}
}
}
技巧 4:不要在 OwnerDrawCell 事件中更改样式 注意上面的技巧 3 中的代码并没有在 OwnerDrawCell 事件中修改作为参数
传递进来的 CellStyle 对象。反而,它为 e.Style 参数指定了一个新的值。
这是非常重要的,因为将 CellStyle 作为参数在事件处理中传递被其他单元格经常使用。例如,你可能在无意间改变了表格中大多数单元格使用的正常样式。
下面的例子说明了他们之间的区别:- Visual Basic
' ** 正确的做法:
Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
' 当绘制这个单元格式选择使用的样式:
e.Style = MyStyleSelector(e.Row, e.Col) End Sub
- C#
// ** 正确的做法:
private void _flex_OwnerDrawCell(object sender,
C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
//当绘制这个单元格式选择使用的样式:
e.Style = MyStyleSelector(e.Row, e.Col);
}
对比下面这个:
Visual Basic
' ** 错误的做法:
Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
' 当绘制这个单元格式选择使用的样式:
' 这是不好的,因为改变任何 CellStyle 对象会导致表格失效, ' 而且将会引起这个事件处理方法被一次又一次的调用。
e.Style.Color = MyColorSelector(e.Row, e.Col)
End Sub- C#
技巧 5:使用 Trimming 属性来在表格的列上显示省略号
// ** 错误的做法:
private void _flex_OwnerDrawCell(object sender,
C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
// 当绘制这个单元格式选择使用的样式:
// 这是不好的,因为改变任何 CellStyle 对象会导致表格失效, // 而且将会引起这个事件处理方法被一次又一次的调用。
e.Style.Color = MyColorSelector(e.Row, e.Col);
}
Trimming 属性应该被使用来在表格的一列上显示省略号。要决定如何裁剪长字符串以适应单元格,Trimming 属性可以被设置为 None、Character、
Word、EllipsisCharacter、EllipsisWord、或 EllipsisPath。 下面的表格描述了每个选项:
选项名称 | 描述 |
Character | 以最接近的字符对指定的文本进行裁剪。 |
EllipsisCharacte | 以最接近的字符对指定的文本进行裁剪,并在最后加上省略号。 |
EllipsisPath | 文字的中心的一部分将会被移除并被省略号代替。这个算法将会尽可能多的保留斜杠分割中的部分。 |
EllipsisWord | 指定的文本被裁剪最近的单词,并在结尾处插入省略号。 |
None | 不进行任何裁剪。 |
Word | 按最近的单次进行裁剪 |
下面的代码设置 Trimming 属性,用来在第二列上的最后展示省略号,并且
将文本内容裁剪为最近的字符:
- Visual Basic
_flex.Cols(1).StyleNew.Trimming = StringTrimming.EllipsisCharacter
- C#
_flex.Cols[1].StyleNew.Trimming =StringTrimming.EllipsisCharacter;
技巧 6:使用 WordWrap 属性来在单元格中显示多行文本 当你想在一个单元格中显示多行文本时,请使用 WordWrap 和 Height 属
性。WordWrap 属性决定表格是否应该自动断开包含空格的长字符串,并将它显示为多行文本。如果字符串中包含硬换行符(vbCrLf 或者"\n\r"),将会一直显示为多行文本。
多行文本可以显示在固定、可滚动的单元格中。例如,在固定单元格中设
置多行文本,请查看在列头或者固定行换行章节(第 202 页)。下面的代码展示了在可滚动的单元格中设置一个多行显示文本:
- Visual Basic
'设置 WordWrap 属性。
_flex.Styles("Normal").WordWrap = True
'设置行高。
_flex.Rows(1).Height = 2 * fg.Rows.DefaultSize
'向单元格中添加文本。
_flex(1, 2) = "This is the first line." & ControlChars.CrLf & " This is the second line."
- C#
// 设置 WordWrap 属性。
_flex.Styles["Normal"].WordWrap = true;
// 设置行高。
_flex.Rows[1].Height = 2 * fg.Rows.DefaultSize;
// 向单元格中添加文本。
_flex[1, 2] = "This is the first line. \r\n This is the second line.";
技巧 7:当绑定到一个 DataTable 时使用 Sort 属性来检索数据进行排序如果表格绑定到一个 DataTable,当数据刷新时,用户可以保持该排序方
式。这可以通过使用默认视图的 Sort 属性和排序表达式。Sort 属性使用一个字符串包含列名的 ASC (对列进行升序排列)或者 DESC(对列进行降序排列)。默认情况下,使用升序排列。多个列的排序可以通过输入每列的列名,中间使用逗号分隔。
一个排序表达式可以包含表格中的列名或者一个计算式。在运行时设置排
序表达式,可以及时的反应数据视图中的变化。
Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.ProductsTableAdapter.Fill(Me.NwindDataSet.Products)
End Sub
Private Sub btn_Sort_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btn_Sort.Click
' 先根据 UnitsInStock 列进行排序,之后根据 ProductID 列进行排序。
Me.ProductsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC"
End Sub
Private Sub btn_ClearSort_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btn_ClearSort.Click
' 清除排序
Me.ProductsBindingSource.Sort = "" End Sub
C#
private void Form1_Load(object sender, System.EventArgs e)
{
this.productsTableAdapter.Fill(this.nwindDataSet.Products);
}
private void btn_Sort_Click(object sender, EventArgs e)
{
//先根据 UnitsInStock 列进行排序,之后根据 ProductID 列进行排序。
this.productsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC";
}
private void btn_ClearSort_Click(object sender, EventArgs e)
{
//清除排序
this.productsBindingSource.Sort = "";
}
技巧 8:使用 SetupEditor 事件来控制在列中输入的字符个数 要在给定的列中,设置用户可以输入的最大字符个数,请使用 SetupEditor
事件。例如,一个 C1TextBox 被设置为 C1FlexGrid 中的编辑器,你必须在
C1FlexGrid 的 StartEdit 中声明使用一个外部编辑器:
- Visual Basic
Private Sub _flex_StartEdit(ByVal sender As System.Object, ByVal e As
C1.Win.C1FlexGrid.RowColEventArgs) Handles _flex.StartEdit
_flex.Editor = C1TextBox End Sub
- C#
private void _flex_StartEdit(object sender,
C1.Win.C1FlexGrid.RowColEventArgs e)
{
_flex.Editor = c1TextBox;
}
现在,你设置了表格中的编辑器,你可以使用下面的代码来允许第三列最
多输入 20 个字符,其他列最多输入 10 个字符(请记住下面的代码必须放到
SetupEditor 事件中):
Visual Basic
Private Sub _flex_SetupEditor(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.RowColEventArgs) Handles _flex.SetupEditor
' 设置第三列最多允许输入 20 个字符其他列最多 10 个。
If e.Col = 2 Then
CType(fg.Editor, C1TextBox).MaxLength = 20 Else
CType(fg.Editor, C1TextBox).MaxLength = 10
End If
End SubC#
private void _flex_SetupEditor(object sender, RowColEventArgs e)
{
// 设置第三列最多允许输入 20 个字符其他列最多 10 个。 if (e.Col == 2)
c1TextBox.MaxLength = 20; else c1TextBox.MaxLength = 10;
}