High performance XAML charts… using Win2D

ScreenCap

Hi! 

Over the last couple of years I got quite a few questions about the Chart control that I ported from Silverlight Toolkit and shared in WinRT XAML Toolkit. Mostly about performance and customizing the design. Well, the update performance is something I recently tweaked a little bit by removing some of the animations, but really – the control is fairly complicated and uses lots of XAML to enable customizing all the different parts and so it works best for static charts with just a few data points. I haven’t actually used the control much, so every time I get asked how to change anything in it – I have to investigate it myself and often get lost in all that code.

A few weeks ago I decided to check how hard would it be to create some charts using immediate mode rendering with Direct2D. Not being too much of a masochist – I used the Win2D wrapper from C# code and came up with a few samples that turn out to work great with charts that update in real time and render at 60FPS. It turns out you can draw one with just a few lines of code, and customizing it is a lot more straightforward than with XAML. The only downsides – you’d still have to write quite a bit of code to make it interactive and accessible, but if you don’t care about it too much – I highly recommend rolling out your own charts using Win2D. Actually I highly recommend using Win2D for just about any dynamic 2D graphics content.

You can find the source for these charts here

It’s fairly simple really to write your own – you add a Win2D package from NuGet, add a CanvasControl from the package to your XAML and handle its Draw event using something like this:

public void RenderData(
    CanvasControl canvas,
    CanvasDrawEventArgs args,
    Color color,
    float thickness,
    List<double> data,
    bool renderArea)
{
    using (var cpb = new CanvasPathBuilder(args.DrawingSession))
    {
        cpb.BeginFigure(new Vector2(0, (float)(canvas.ActualHeight * (1 - data[0]))));

        for (int i = 1; i &lt; data.Count; i++)
        {
            cpb.AddLine(new Vector2(i, (float)(canvas.ActualHeight * (1 - data[i]))));
        }

        if (renderArea)
        {
            cpb.AddLine(new Vector2(data.Count, (float)canvas.ActualHeight));
            cpb.AddLine(new Vector2(0, (float)canvas.ActualHeight));
            cpb.EndFigure(CanvasFigureLoop.Closed);
            args.DrawingSession.FillGeometry(CanvasGeometry.CreatePath(cpb), Colors.LightGreen);
        }
        else
        {
            cpb.EndFigure(CanvasFigureLoop.Open);
            args.DrawingSession.DrawGeometry(CanvasGeometry.CreatePath(cpb), color, thickness);
        }
    }
}

Voila! – you’ve got yourself a way to render tons of data points, moving averages, pie charts, with candlesticks etc. in real time! Check out the project on github for the source of all the sample parts.

ScreenCapPieChart

Advertisements
Tagged , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: