How to Improve WPF Datagrid Performance with 2D Cell Rendering
Tags: webdev, devops, dotnet, csharp
Published: 2023-05-18 15:03:15

---
canonical_url: https://developer.mescius.com/blogs/how-to-improve-wpf-datagrid-performance-with-2d-cell-rendering
description: Learn how to boost WPF datagrid application performance by over 30% with new 2D cell rendering features. See more from ComponentOne today.
---
New in the ComponentOne 2023 v1 release, FlexGrid for WPF and MAUI supports custom cell creation using the .NET 2D drawing API. By using the graphics drawing API (such as _DrawString_ or _DrawLine_), you can gain performance improvements of up to 37% for loading and scrolling, compared to using Framework Elements for custom cells.

In this blog, we will explain the different techniques for custom cell creation in the XAML FlexGrid, show an example using the new 2D drawing approach, and share the new performance gains.

## FlexGrid Custom Cell Rendering Techniques

The standard approaches to customizing cells in FlexGrid for XAML platforms are either through the **GridCellFactory** (C#) or the **CellTemplate** (XAML). The CellTemplate property allows you to define a DataTemplate in XAML to represent a cell’s content. This approach is still useful for some cases when you need to customize the cell’s content with specific UI controls (like a gauge component). But there are common cases, like displaying plain text and shapes, where drawing the cell content with the 2D rendering API will improve performance.

Basically, calling the _DrawString_ method 100 times is more efficient than rendering 100 TextBlocks.

To access the drawing API (System.Drawing), we need to use the **GridCellFactory** approach to access the C# code. The GridCellFactory allows the customization of cell content by overriding the methods _GetCellContentType_, _CreateCellContent_, _BindCellContent,_ and _UnbindCellContent_. While this approach also allows you to render cells with UI Framework Elements (like a TextBlock), it now also allows you to use rendering APIs.

To explain how to do it, we will implement this tic-tac-toe demo using FlexGrid.

![2D](https://files.grapecity.com/gc-website-media/0q5nb4ix/01-2d.png?width=302&height=306)

## Example Rendering Cells with 2D Rendering API

The first step is creating a custom Cell Factory and enabling custom cells. Note that custom cells are disabled by default to avoid breaking changes in the code of previously developed cell factories.

```
    public class MyCellFactory : GridCellFactory
    {
        public MyCellFactory()
        {
            AllowCustomCells = true;
        }
    }
```

Then we override the methods _GetCellKind_, _CreateCell_, _BindCell,_ and _UnbindCell_, to implement the desired cell content. Notice that these methods are similar to those used above to create the cell content; because the cells are reused and recycled, it is necessary to specify what kind of cells we’re customizing so the recycling algorithm works correctly.

For simplicity reasons, we will assume all the cells are of the same kind in the code below:

```
    public override object GetCellKind(GridCellType cellType, GridCellRange range)
    {
        return typeof(MyCustomCell);
    }

    public override GridCellView CreateCell(GridCellType cellType, GridCellRange range, object cellKind)
    {
        return new MyCustomCell();
    }

    public override void BindCell(GridCellType cellType, GridCellRange range, GridCellView cell)
    {
        (cell as MyCustomCell).IsCross = isCross;//Sets the value to determine whether the cell shows a cross of a circle
    }

    public override void UnbindCell(GridCellType cellType, GridCellRange range, GridCellView cell)
    {
    }
```

The class MyCustomCell will implement the custom drawing. In WPF, we can override the OnRender method to perform the drawing. Still, we will override OnRenderBackground provided by GridCellView so the drawing of the border is performed by the base class, and we don’t need to deal with it. Within this override, we draw the desired tic-tac-toe symbol using the _DrawLine_ or _DrawEllipse_ methods.

```
    public class MyCustomCell : GridCellView
    {
        private bool _isCross;
        public bool IsCross
        {
            get => _isCross;
            set
            {
                _isCross = value;
                InvalidateVisual();
            }
        }

        protected override void OnRenderBackground(DrawingContext drawingContext, Rect backgroundArea)
        {
            base.OnRenderBackground(drawingContext, backgroundArea);
            backgroundArea.Inflate(-8, -8);//Adds some padding
            if (IsCross)
            {
                drawingContext.DrawLine(new Pen(Foreground, 4), backgroundArea.TopLeft, backgroundArea.BottomRight);
                drawingContext.DrawLine(new Pen(Foreground, 4), backgroundArea.BottomLeft, backgroundArea.TopRight);
            }
            else
            {
                drawingContext.DrawEllipse(null, new Pen(Foreground, 4), new Point(backgroundArea.Left + backgroundArea.Width / 2, backgroundArea.Top + backgroundArea.Height / 2), backgroundArea.Width / 2, backgroundArea.Height / 2);
            }
        }
    }
```

Next, let us also show how to define the Cell Factory in XAML. Here we’ve defined a FlexGrid with three rows and three columns to simulate the tic-tac-toe board.

```
    <c1:FlexGrid AutoGenerateColumns="False" DefaultColumnWidth="100" DefaultRowHeight="100" 
       GridLinesVisibility="All" HeadersVisibility="None" SelectionMode="None" IsReadOnly="True">
        <c1:FlexGrid.Rows>
            <c1:GridRow />
            <c1:GridRow />
            <c1:GridRow />
        </c1:FlexGrid.Rows>
        <c1:FlexGrid.Columns>
            <c1:GridColumn />
            <c1:GridColumn />
            <c1:GridColumn />
        </c1:FlexGrid.Columns>
        <c1:FlexGrid.CellFactory>
            <local:MyCustomCellFactory />
        </c1:FlexGrid.CellFactory>
    </c1:FlexGrid>
```

The full sample can be downloaded [here](https://github.com/GrapeCity/ComponentOne-WPF-Samples/tree/master/NET_6/Grid/FlexGridExplorer).

## Observing Performance Improvements

In our tests, we’ve observed up to 37% performance improvements using the DrawLine method compared to alternatives like images or Framework Elements for the cells. Specifically, the reduced loading time and faster scrolling speed will observe performance gains no matter how many rows of data you have.

<table border="0" width="760" style="font-weight: 400;">

<tbody>

<tr>

<td></td>

<td>

Load-time

</td>

<td>

Scrolling

</td>

</tr>

<tr>

<td>

WPF

</td>

<td>

34% faster

</td>

<td>

37% faster

</td>

</tr>

<tr>

<td>

Android

</td>

<td>

34% faster

</td>

<td>

36% faster

</td>

</tr>

<tr>

<td>

iOS

</td>

<td>

32% faster

</td>

<td>

36% faster

</td>

</tr>

</tbody>

</table>