Page tree
Skip to end of metadata
Go to start of metadata

下面的一些技巧是由 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.BeginUpdate();
//做修改。
try
{
for (int r = 0; r < _flex.Rows.Count; r++)
{
For (int c = 0; c < _flex.Cols.Count; c++)
{

_flex[r, c] = r + c;


}
}
}
finally
{
//完成后调用 EndUpdate 。
_flex.EndUpdate();
}



注意,使用 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 Sub

  • C#

    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 属性可以被设置为 NoneCharacter
WordEllipsisCharacterEllipsisWord、或 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 Sub

  • C#

    private void _flex_SetupEditor(object sender, RowColEventArgs e)
    {
    // 设置第三列最多允许输入 20 个字符其他列最多 10 个。 if (e.Col == 2)
    c1TextBox.MaxLength = 20; else c1TextBox.MaxLength = 10;
    }

  • No labels