The following tips were compiled from frequently asked user questions posted in the C1FlexGrid forum.
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. |
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. |
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"]; } } } |
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); } |
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; |
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."; |
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; } |