I am thinking about converting one of my apps over to WPF, and one of my main concerns was the performance of the DataGrid control (my user’s computers are outdated XP machines with no dedicated graphics). I experimented with a few thousand rows and scrolling performance was horrible.
I was wondering if there is a way to set the datagrid cell’s content to a custom class that derives from FrameworkElement?
Here is a sample class that appears to have much better performance when put in a virtualizing stackpanel:
public class LiteTextBlock : FrameworkElement
{
private Size _mySize;
private string _myText;
private double totalWidth;
private GlyphTypeface _typeface;
private int _fontSize;
private GlyphRun _run;
public LiteTextBlock(Size mySize, string myText, GlyphTypeface typeface, int fontSize)
{
_mySize = mySize;
this.Width = _mySize.Width;
this.Height = _mySize.Height;
_myText = myText + " additional information";
_typeface = typeface;
_fontSize = fontSize;
}
protected override void OnRender(DrawingContext drawingContext)
{
if (_run == null)
{
totalWidth = 0;
ushort[] glyphIndexes = new ushort[_myText.Length];
double[] advanceWidths = new double[_myText.Length];
for (int i = 0; i < _myText.Length; i++)
{
ushort glyphIndex = _typeface.CharacterToGlyphMap[_myText[i]];
double width = _typeface.AdvanceWidths[glyphIndex] * _fontSize;
if (totalWidth + width >= _mySize.Width - 10)
{
Array.Resize(ref glyphIndexes, i);
Array.Resize(ref advanceWidths, i);
break;
}
glyphIndexes[i] = glyphIndex;
advanceWidths[i] = width;
totalWidth += width;
}
Point origin = new Point(5, 0);
_run = new GlyphRun(_typeface, 0, false, _fontSize, glyphIndexes
, origin, advanceWidths, null, null, null, null, null, null);
}
drawingContext.DrawGlyphRun(Brushes.Black, _run);
}
}
Can anyone show me if this is possible?
Disclaimer: I have already tried using lighter-weight controls such as the ListView, but performance was still poor.
Yes, there is a way.
You need to implement your custom DataGridColumn and override its GenerateElement method and you need to handle DataGrid.AutoGeneratingColumn event to set your custom DataGridColumn to DataGrid.
Here is a sample for custom DataGridColumn:
Here is a handler for DataGrid.AutoGeneratingColumn event:
This code will work for displaying values, although LiteTextBlock constructor size parameters are probably not set to appropriate values. To edit values you must also implement GenerateEditingElement method.