Use Maui.Graphics to Draw 2D Graphics in Any .NET Application
This week Microsoft officially released .NET Maui and the new Microsoft.Maui.Graphics
library which can draw 2D graphics in any .NET application (not just Maui apps). This page offers a quick look at how to use this new library to draw graphics using SkiaSharp in a .NET 6 console application. The C# Data Visualization site has additional examples for drawing and animating graphics using Microsoft.Maui.Graphics
in Windows Forms and WPF applications.

The code below is a full .NET 6 console application demonstrating common graphics tasks (setting colors, drawing shapes, rendering text, etc.) and was used to generate the image above.
// These packages are available on NuGet
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Skia;
// Create a bitmap in memory and draw on its Canvas
SkiaBitmapExportContext bmp = new(600, 400, 1.0f);
ICanvas canvas = bmp.Canvas;
// Draw a big blue rectangle with a dark border
Rect backgroundRectangle = new(0, 0, bmp.Width, bmp.Height);
canvas.FillColor = Color.FromArgb("#003366");
canvas.FillRectangle(backgroundRectangle);
canvas.StrokeColor = Colors.Black;
canvas.StrokeSize = 20;
canvas.DrawRectangle(backgroundRectangle);
// Draw circles randomly around the image
for (int i = 0; i < 100; i++)
{
float x = Random.Shared.Next(bmp.Width);
float y = Random.Shared.Next(bmp.Height);
float r = Random.Shared.Next(5, 50);
Color randomColor = Color.FromRgb(
red: Random.Shared.Next(255),
green: Random.Shared.Next(255),
blue: Random.Shared.Next(255));
canvas.StrokeSize = r / 3;
canvas.StrokeColor = randomColor.WithAlpha(.3f);
canvas.DrawCircle(x, y, r);
}
// Measure a string
string myText = "Hello, Maui.Graphics!";
Font myFont = new Font("Impact");
float myFontSize = 48;
canvas.Font = myFont;
SizeF textSize = canvas.GetStringSize(myText, myFont, myFontSize);
// Draw a rectangle to hold the string
Point point = new(
x: (bmp.Width - textSize.Width) / 2,
y: (bmp.Height - textSize.Height) / 2);
Rect myTextRectangle = new(point, textSize);
canvas.FillColor = Colors.Black.WithAlpha(.5f);
canvas.FillRectangle(myTextRectangle);
canvas.StrokeSize = 2;
canvas.StrokeColor = Colors.Yellow;
canvas.DrawRectangle(myTextRectangle);
// Daw the string itself
canvas.FontSize = myFontSize * .9f; // smaller than the rectangle
canvas.FontColor = Colors.White;
canvas.DrawString(myText, myTextRectangle,
HorizontalAlignment.Center, VerticalAlignment.Center, TextFlow.OverflowBounds);
// Save the image as a PNG file
bmp.WriteToFile("console2.png");
Multi-Platform Graphics Abstraction
The Microsoft.Maui.Graphics
namespace a small collection of interfaces which can be implemented by many different rendering technologies (SkiaSharp, SharpDX, GDI, etc.), making it possible to create drawing routines that are totally abstracted from the underlying graphics rendering system.
I really like that I can now create a .NET Standard 2.0 project that exclusively uses interfaces from Microsoft.Maui.Graphics
to write code that draws complex graphics, then reference that code from other projects that use platform-specific graphics libraries to render the images.
When I write scientific simulations or data visualization code I frequently regard my graphics drawing routines as business logic, and drawing with Maui.Graphics lets me write this code to an abstraction that keeps rendering technology dependencies out of my business logic - a big win!
Rough Edges
After working with this library while it was being developed over the last few months, these are the things I find most limiting in my personal projects which made it through the initial release this week. Some of them are open issues so they may get fixed soon, and depending on how the project continues to evolve many of these rough edges may improve with time. I’m listing them here now so I can keep track of them, and I intend to update this list if/as these topics improve:
-
Strings cannot be accurately measured: The size returned by
GetStringSize()
is inaccurate and does not respect font. There’s an issue tracking this (#279), but it’s been open for more than three months and the library was released this week in its broken state.- EDIT: I concede multi-platform font support is a very hard problem, but this exactly the type of problem that .NET Maui was created to solve.
- EDIT: I concede multi-platform font support is a very hard problem, but this exactly the type of problem that .NET Maui was created to solve.
-
Missing XML documentation: Intellisense can really help people who are new to a library. The roll-out of a whole new application framework is a good example of a time when a lot of people will be exploring a new library. Let’s take the
Color
class for example (which 100% of people will interact with) and consider misunderstandings that could be prevented by XML documentation and intellisense: Ifnew Color()
accepts 3 floats, should they be 0-255 or 0-1? I need to make a color from the RGB web value#003366
, why doesColor.FromHex()
tell me to useFromArgb
? Web colors are RGBA, should I useFromRrgba()
? But wait, that string is RGB, not ARGB or RGBA, so will it throw an exception? What doesColor.Parse()
do?-
Edit 1: Some of these answers are documented in source code, but they are not XML docs, so this information is not available to library users.
-
Edit 2: Is it on the open-source community to contribute XML documentation? If so, fair enough, but it is a very extensive effort (to write and to review), so a call should be put out for this job to ensure someone doesn’t go through all the effort then have their open PR sit unmerged for months while it falls out of sync with the main branch.
-
-
The library has signs of being incomplete: There remain a good number of NotImplementedException and // todo in sections of the code base that indicate additional work is still required.
Again, I’m pointing these things out the very first week .NET Maui was released, so there’s plenty of time and opportunity for improvements in the coming weeks and months.
I’m optimistic this library will continue to improve, and I am very excited to watch it progress! I’m not aware of the internal pressures and constraints that led to the library being released like it was this week, but I want to end by complimenting the team on their great job so far and encourage everyone (at Microsoft and in the open-source community at large) to keep moving this library forward. The .NET Maui team undertook an ambitious challenge by setting-out to implement cross-platform graphics support, but achieving this goal elegantly will be a huge accomplishment for the .NET community!