Use Data Virtualization
To efficiently render large data sets, FlexGrid supports data vitualization in which data is fetched in pages as the user scrolls down. The grid knows the total number of rows but only loads and displays those that are visible to the user. For instance, you can use C1.DataCollection package to implement virtualizable data source. Create a class inherited from the C1VirtualDataCollection and implement GetPageAsync method which returns one page of data from data source you have assigned. The following GIF shows how FlexGrid appears in the virtual scrolling mode.

public class VirtualModeCollectionView : C1VirtualDataCollection<Customer>
{
public int TotalCount { get; set; } = 1_000;
protected override async Task<Tuple<int, IReadOnlyList<Customer>>> GetPageAsync(int pageIndex, int startingIndex, int count, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpression = null, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Delay(500, cancellationToken);//Simulates network traffic.
return new Tuple<int, IReadOnlyList<Customer>>(TotalCount, Enumerable.Range(startingIndex, count).Select(i => new Customer(i)).ToList());
}
}
Public Class VirtualModeCollectionView
Inherits C1VirtualDataCollection(Of Customer)
Public Property TotalCount As Integer = 1_000
Protected Overrides Async Function GetPageAsync(ByVal pageIndex As Integer, ByVal startingIndex As Integer, ByVal count As Integer, ByVal Optional sortDescriptions As IReadOnlyList(Of SortDescription) = Nothing, ByVal Optional filterExpression As FilterExpression = Nothing, ByVal Optional cancellationToken As CancellationToken = DirectCast(Nothing, CancellationToken)) As Task(Of Tuple(Of Integer, IReadOnlyList(Of Customer)))
Await Task.Delay(500, cancellationToken) 'Simulates network traffic.
Return New Tuple(Of Integer, IReadOnlyList(Of Customer))(TotalCount, Enumerable.Range(CInt(startingIndex), CInt(count)).[Select](Function(i) New Customer(i)).ToList())
End Function
End Class
Use BeginUpdate and EndUpdate Methods
The BeginUpdate and EndUpdate methods are used to optimize the performance of the grid. Call BeginUpdate before making extensive changes, and call EndUpdate when done to suspend repainting. This reduces flicker and increases performance. This optimization is especially effective when adding large number of rows to the grid, because it needs to recalculate ranges and update scrollbars each time a row is added.
The code below shows how to add a large number of rows to the WinForms FlexGrid efficiently. Note how the EndUpdate method is called inside a 'finally' block to ensure repainting is properly restored.
void UpdateGrid(C1FlexGrid c1FlexGrid1)
{
try
{
c1FlexGrid1.BeginUpdate(); // suspend painting to avoid flicker
c1FlexGrid1.Rows.Count = 1;
for (int i = 1; i < 10000; i++)
c1FlexGrid1.AddItem("Row " + i.ToString());
}
finally
{
c1FlexGrid1.EndUpdate(); // always restore painting
}
}
Private Sub UpdateGrid(ByVal c1FlexGrid1 As C1FlexGrid)
Try
c1FlexGrid1.BeginUpdate() ' suspend painting to avoid flicker
c1FlexGrid1.Rows.Count = 1
For i As Integer = 1 To 10000 - 1
c1FlexGrid1.AddItem("Row " & i.ToString())
Next
Finally
c1FlexGrid1.EndUpdate() ' always restore painting
End Try
End Sub
Keep AutoResize Property to False (default)
In case of bound grid, if property is set to true, the control automatically resizes its columns to fit the widest entry every time new data is read from the data source. If the data source contains a large number of rows and columns, the automatic resizing may take a relatively long time. In such cases, you should consider setting AutoResize to false and setting the column widths directly in code.
Assign Styles Dynamically
FlexGrid allows you to create cell styles and assign them to rows, columns, and arbitrary cell ranges. You can use this feature to format the grid cells conditionally. Usually, you do this by using the method. However, in that case you have to update the style whenever the cell value changes. Also, if the grid is bound to a data source, styles are lost whenever data source is reset after operations such as sorting and filtering. A better alternative in these cases is to use the OwnerDraw feature and select styles dynamically based on the cell values. For example, the sample code shows how to display negative values in red color and values above 1,000 in green color in the WinForms FlexGrid.
private void Form1_Load(object sender, EventArgs e)
{
// Fill a column with random values.
c1FlexGrid1.Cols[1].DataType = typeof(int);
Random rnd = new Random();
for (int r = 1; r < c1FlexGrid1.Rows.Count; r++)
{
c1FlexGrid1[r, 1] = rnd.Next(-10000, 10000);
}
// Create style used to show negative values.
c1FlexGrid1.Styles.Add("Red").ForeColor = Color.Red;
// Enable OwnerDraw by setting the DrawMode property.
c1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
c1FlexGrid1.OwnerDrawCell += new C1.Win.C1FlexGrid.OwnerDrawCellEventHandler(C1FlexGrid1_OwnerDrawCell);
}
private void C1FlexGrid1_OwnerDrawCell(object sender, OwnerDrawCellEventArgs e)
{
if(!e.Measuring)
{
// Check that the row and column contain integer data.
if (e.Row > 0 && c1FlexGrid1.Cols[e.Col].DataType == typeof(int))
{
// Apply the style "Red"
e.Style = c1FlexGrid1.Styles["Red"];
}
}
}
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
' Fill a column with random values.
c1FlexGrid1.Cols(1).DataType = GetType(Integer)
Dim rnd As Random = New Random()
For r As Integer = 1 To c1FlexGrid1.Rows.Count - 1
c1FlexGrid1(r, 1) = rnd.[Next](-10000, 10000)
Next
' Create style used to show negative values.
c1FlexGrid1.Styles.Add("Red").ForeColor = Color.Red
' Enable OwnerDraw by setting the DrawMode property.
c1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw
c1FlexGrid1.OwnerDrawCell += New C1.Win.C1FlexGrid.OwnerDrawCellEventHandler(AddressOf C1FlexGrid1_OwnerDrawCell)
End Sub
Private Sub C1FlexGrid1_OwnerDrawCell(ByVal sender As Object, ByVal e As OwnerDrawCellEventArgs)
If Not e.Measuring Then
' Check that the row and column contain integer data.
If e.Row > 0 AndAlso c1FlexGrid1.Cols(e.Col).DataType Is GetType(Integer) Then
' Apply the style "Red"
e.Style = c1FlexGrid1.Styles("Red")
End If
End If
End Sub
Avoid Modifying Styles in the OwnerDrawCell Event
Another way to improve performance is not to modify the object passed as a parameter in the OwnerDrawCell event. Instead, assign a new value to the e.Style parameter. This is important because the CellStyle passed to the event handler is often used by other cells. For example, you could, unintentionally change a normal style of the WinForms FlexGrid, which would affect other similar cells as well in the grid.
// ** CORRECT APPROACH:
private void C1FlexGrid1_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
// Select style to use when painting this cell:
e.Style = MyStyleSelector(e.Row, e.Col);
}
// ** WRONG APPROACH:
private void C1FlexGrid1_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
// Select style to use when painting this cell:
// This is wrong 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);
}
' ** CORRECT APPROACH:
Private Sub C1FlexGrid1_OwnerDrawCellMethod(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs)
' Select style to use when painting this cell:
e.Style = MyStyleSelector(e.Row, e.Col)
End Sub
' ** WRONG APPROACH:
Private Sub C1FlexGrid1_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs)
' Select style to use when painting this cell:
' This is wrong 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
Show Ellipses in a Single Column
The 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. For more information on trimming, see Display Trimmed Text.
The following code sets the Trimming property to show ellipses at the end of the second WinForms Flexgrid column, with the text trimmed to the nearest character:
c1FlexGrid1.Cols[1].StyleNew.Trimming =StringTrimming.EllipsisCharacter;
c1FlexGrid1.Cols(1).StyleNew.Trimming = StringTrimming.EllipsisCharacter
Show Multi-line Text in a Cell
When showing multiple lines of text in a cell, use the 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 more information on word wrapping, see Wrap Text.
Refer to code below to see how a multi-line text should be effectively displayed in the WinForms FlexGrid.
// Set the WordWrap property.
c1FlexGrid1.Styles["Normal"].WordWrap = true;
// Set the row height.
c1FlexGrid1.Rows[1].Height = 2 * fg.Rows.DefaultSize;
// Add text to the cell.
c1FlexGrid1[1, 2] = "This is the first line. \r\n This is the second line.";
' Set the WordWrap property.
c1FlexGrid1.Styles("Normal").WordWrap = True
' Set the row height.
c1FlexGrid1.Rows(1).Height = 2 * fg.Rows.DefaultSize
' Add text to the cell.
c1FlexGrid1(1, 2) = "This is the first line. " & vbCrLf & " This is the second line."
Retrieve Data Sorting When Bound to a Data Table
To maintain the way the grid is sorted when data is refreshed, you can use the default view's property and a sort expression. The Sort property uses a string containing the column name followed by ASC(default) or DESC to sort the column in ascending or descending order respectively. Multiple columns can be sorted by specifying 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.
Below code shows how to use the sort expression with Sort property in the WinForms FlexGrid.
// Sort the data by the UnitsInStock column then by the ProductID column.
this.productsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC";
' Sort the data by the UnitsInStock column then by the ProductID column.
Me.productsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC"
Specify Character Limit for Column
To set the maximum number of characters a user can enter for any given column, use the SetupEditor event. You must declare an external editor such as C1TextBox in the StartEdit event of the class. Then, in the SetupEditor event, you can set the maximum number of characters that are allowed in a column cell.
Use the code below to set the character limit for a WinForms FlexGrid column.
private void C1FlexGrid1_StartEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
{
c1FlexGrid1.Editor = c1TextBox;
}
private void C1FlexGrid1_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;
}
Private Sub C1FlexGrid1_StartEdit(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.RowColEventArgs)
c1FlexGrid1.Editor = c1TextBox
End Sub
Private Sub C1FlexGrid1_SetupEditor(ByVal sender As Object, ByVal e As RowColEventArgs)
' Set the 3rd column to allow 20 characters and the rest only 10.
If e.Col = 2 Then
c1TextBox.MaxLength = 20
Else
c1TextBox.MaxLength = 10
End If
End Sub