ComponentOne FlexGrid for WinForms
FlexGrid for WinForms Top Tips

The following tips were compiled from frequently asked user questions posted in the C1FlexGrid forum.

Tip 1: Use the BeginUpdate/EndUpdate Methods to Increase Performance

Every time a cell value is changed, or rows and columns are added or removed from the grid, some calculations are performed in order to recalculate the grid layout and update the display.

You can increase performance significantly by enclosing the changes in calls to the BeginUpdate and EndUpdate methods. For example:

To write code in Visual Basic

Visual Basic
Copy Code
' call BeginUpdate before updating the grid.
_flex. BeginUpdate()
 
' Make the changes.
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
 
    ' Always call EndUpdate when done.
    _flex.EndUpdate()
End Try

To write code in C#

C#
Copy Code
// call BeginUpdate before updating the grid.
_flex.BeginUpdate();
 
// Make the changes.
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
{
 
    // Always call EndUpdate when done.
    _flex.EndUpdate();
}

Note the use of a try/finally block to ensure that the C1FlexGridBase.EndUpdate method is called even if the update code fails and throws an exception.

Note: The BeginUpdate and EndUpdate methods were added in the 2010/v1 release of the C1FlexGrid. In previous versions, the Redraw property was used for the same purpose. This change was made to increase source compatibility with other controls that use the BeginUpdate and EndUpdate pattern.

Tip 2: Use the AutoResize Property to Increase Performance

When a bound grid retrieves data from a data source, it measures every cell and sets the column widths so they fit all the data. This ensures the grid layout is optimal to display the data in the data source, but it can be time-consuming if the data source is large (say more than a few thousand rows).

In these cases, you should consider setting the AutoResize property to False and setting the column widths in code.

Note: Starting with the 2010/v1 release of the C1FlexGrid, the AutoResize property defaults to False. If your data source contains a relatively small number of items and you want the grid to resize the columns automatically, you can either set the AutoResize property to True manually or simply call the AutoSizeCols methods after binding or populating the grid. This change was made to increase performance in cases where the grid is bound to large data sources.

Tip 3: Use the DrawMode Property to Assign Styles Dynamically Based on Cell Values

The grid allows you to create cell styles and assign them to rows, columns, and arbitrary cell ranges. You can use this capability to format cells based on their values. For example, cells that contain negative values can display them in red.

You can do this by assigning styles to cells with the SetCellStyle method, but in this case you have to update the style whenever the cell value changes. Also, if the grid is bound to a data source, styles will be lost whenever the data source is reset (after sorting and filtering operations for example).

A better alternative in these cases is to use the grid's OwnerDraw feature and select styles dynamically, based on the cell values. For example, the code below shows negative values in red and values above 1,000 in green:

To write code in Visual Basic

Visual Basic
Copy Code
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
    ' Fill a column with random values.
    _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
 
    ' Create style used to show negative values.
    _flex.Styles.Add("Red").ForeColor = Color.Red
 
    ' Create style used to show values >= 1000.
    _flex.Styles.Add("Green").ForeColor = Color.Green
 
    ' Enable OwnerDraw by setting the DrawMode property.
    _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
 
    ' Check that the row and column contain integer data.
    If ((e.Row > 0) AndAlso (_flex.Cols(e.Col).DataType Is GetType(Integer))) Then
 
        ' Get value in cell about to be painted.
        Dim value As Integer = CInt(_flex(e.Row, e.Col))
        If (value < 0) Then
 
            ' If the Cell value < 0, use the Red style.
            e.Style = _flex.Styles("Red")
        ElseIf (value >= 1000) Then
 
            ' If the Cell value >= 1000, use the Green style.
            e.Style = _flex.Styles("Green")
        End If
    End If
End Sub

To write code in C#

C#
Copy Code
private void Form1_Load(object sender, EventArgs e)
{
 
    // Fill a column with random values.
    _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);
    }
 
    // Create style used to show negative values.
    _flex.Styles.Add("Red").ForeColor = Color.Red;
 
    // Create style used to show values >= 1000.
    _flex.Styles.Add("Green").ForeColor = Color.Green;
 
    // Enable OwnerDraw by setting the DrawMode property.
    _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)
{
 
    // Check that the row and column contain integer data.
    if (e.Row > 0 && _flex.Cols[e.Col].DataType == typeof(int))
    {
 
        // Get value in cell about to be painted.
        int value = (int)_flex[e.Row, e.Col];
        if (value < 0)
        {
 
            // If the Cell value < 0, use the Red style.
            e.Style = _flex.Styles["Red"];
        }
        else if (value >= 1000)
        {
 
           // If the Cell value >= 1000, use the Green style.
           e.Style = _flex.Styles["Green"];
        }
    }
}

Tip 4: Do Not Modify Styles in the OwnerDrawCell Event

Note that the code in Tip 3 does not modify the CellStyle object passed as a parameter in the OwnerDrawCell event. Instead, it assigns a new value to the e.Style parameter.

That is important because the CellStyle passed to the event handler is often used by other cells. For example, you could, unintentionally change the grid's normal style, which would affect most cells in the grid.

The examples below illustrate the difference:

To write code in Visual Basic

Visual Basic
Copy Code
' ** CORRECT APPROACH:
Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
 
    ' Select style to use when painting this cell:
    e.Style = MyStyleSelector(e.Row, e.Col)
End Sub

To write code in C#

C#
Copy Code
// ** CORRECT APPROACH:
private void _flex_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
 
    // Select style to use when painting this cell:
    e.Style = MyStyleSelector(e.Row, e.Col);

Contrast this with the following:

To write code in Visual Basic

Visual Basic
Copy Code
' ** WRONG APPROACH:
Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
 
    ' Select style to use when painting this cell:
    ' This is bad because changing any CellStyle objects invalidates the
    ' grid, which would cause this event handler to be called over and
    ' over again.
    e.Style.Color = MyColorSelector(e.Row, e.Col)
End Sub

To write code in C#

C#
Copy Code
// ** WRONG APPROACH:
private void _flex_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
 
    // Select style to use when painting this cell:
    // This is bad because changing any CellStyle objects invalidates the
    // grid, which would cause this event handler to be called over and
    // over again.
    e.Style.Color = MyColorSelector(e.Row, e.Col);
}

Tip 5: Use the Trimming Property to Show Ellipses in a Single Column of the Grid

The Trimming property should be used to show ellipses in a single column of the grid. To determine how long strings are trimmed to fit the cell, the Trimming property can be set to either None, Character, Word, EllipsisCharacter, EllipsisWord, or EllipsisPath.

The following table describes each of the be trimming options:

Member Name Description
Character Specifies that the text is trimmed to the nearest character.
EllipsisCharacter Specifies that the text is trimmed to the nearest character, and an ellipsis is inserted at the end of a trimmed line.
EllipsisPath The center is removed from the trimmed lines and replaced by an ellipsis. The algorithm keeps as much of the last slash-delimited segment of the line as possible.
EllipsisWord Specifies that the text is trimmed to the nearest word and an ellipsis is inserted at the end of a trimmed line.
None Specifies no trimming.
Word Specifies that the text is trimmed to the nearest word.

The following code sets the Trimming property to show ellipses at the end of the second column, with the text trimmed to the nearest character:

To write code in Visual Basic

Visual Basic
Copy Code
_flex.Cols(1).StyleNew.Trimming StringTrimming.EllipsisCharacter

To write code in C#

C#
Copy Code
_flex.Cols[1].StyleNew.Trimming =StringTrimming.EllipsisCharacter;

Tip 6: Use the WordWrap Property to Show Multiple Line Text in a Cell

When showing multiple lines of text in a cell, use the WordWrap and Height properties. The WordWrap property determines whether the grid should automatically break long strings that contain spaces and display them in multiple lines. Strings that contain hard line breaks (vbCrLf or "\n\r") are always displayed in multiple lines.

Multiple line text can be displayed in both fixed and scrollable cells. For an example setting multiple line text in a fixed cell, see Word Wrapping in a Header or Fixed Row.

The following code sets display multiple line text in a scrollable cell:

To write code in Visual Basic

Visual Basic
Copy Code
' Set the WordWrap property.
_flex.Styles("Normal").WordWrap = True
 
' Set the row height.
_flex.Rows(1).Height = 2 * fg.Rows.DefaultSize
 
' Add text to the cell.
_flex(1, 2) = "This is the first line." & ControlChars.CrLf & " This is the second line."

To write code in C#

C#
Copy Code
// Set the WordWrap property.
_flex.Styles["Normal"].WordWrap = true;
 
// Set the row height.
_flex.Rows[1].Height = 2 * fg.Rows.DefaultSize;
 
// Add text to the cell.
_flex[1, 2] = "This is the first line. \r\n This is the second line.";

Tip 7: Use the Sort Property to Retrieve Data Sorting when Bound to a DataTable

If the grid is bound to a DataTable, the user can maintain the way the grid is sorted when data is refreshed. This can be achieved by using the default view's Sort property and a sort expression.

The Sort property uses a string containing the column name followed by ASC (to sort the column in ascending order) or DESC (to sort the column in descending order). By default, columns are sorted in ascending order. Multiple columns can be sorted by entering each column name separated by a comma.

A sort expression can include names of grid columns or a calculation. Setting the sort expression at run time immediately reflects the changes in the data view.

To write code in Visual Basic

Visual Basic
Copy Code
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
 
    ' Sort the data by the UnitsInStock column then by the ProductID column.
    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
 
    ' Clear the sort.
    Me.ProductsBindingSource.Sort = ""
End Sub

To write code in C#

C#
Copy Code
private void Form1_Load(object sender, System.EventArgs e)
{
    this.productsTableAdapter.Fill(this.nwindDataSet.Products);
}
 
private void btn_Sort_Click(object sender, EventArgs e)
{
    // Sort the data by the UnitsInStock column then by the ProductID column.
    this.productsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC";
}
 
private void btn_ClearSort_Click(object sender, EventArgs e)
{
    // Clear the sort.
    this.productsBindingSource.Sort = "";
}

Tip 8: Control the Number of Characters to be Entered in a Column with the SetupEditor Event

To set the maximum number of characters a user can enter for any given column use the SetupEditor event. For this example a C1TextBox has been set as the editor for C1FlexGrid. You must declare an external editor to be used with C1FlexGrid in the StartEdit event:

To write code in Visual Basic

Visual Basic
Copy Code
Private Sub _flex_StartEdit(ByVal sender As System.Object, ByVal e As C1.Win.C1FlexGrid.RowColEventArgs) Handles _flex.StartEdit
    _flex.Editor = C1TextBox
End Sub

To write code in C#

C#
Copy Code
private void _flex_StartEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
{
    _flex.Editor = c1TextBox;
}

Now that you have the grid's editor set up you can use the following code to allow 20 characters to be entered in the 3rd column and only 10 characters to be entered in the rest of the grid's columns (remember the following code must be entered in the SetupEditor event):

To write code in Visual Basic

Visual Basic
Copy Code
Private Sub _flex_SetupEditor(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.RowColEventArgs) Handles _flex.SetupEditor
 
    ' Set the 3rd column to allow 20 characters and the rest only 10.
    If e.Col = 2 Then
        CType(fg.Editor, C1TextBox).MaxLength = 20
    Else
        CType(fg.Editor, C1TextBox).MaxLength = 10
    End If
End Sub

To write code in C#

C#
Copy Code
private void _flex_SetupEditor(object sender, RowColEventArgs e)
{
 
    // Set the 3rd column to allow 20 characters and the rest only 10.
    if (e.Col == 2)
        c1TextBox.MaxLength = 20;
    else
        c1TextBox.MaxLength = 10;
}