This example demonstrates how to draw graphics in WPF. We lay-out a Canvas
with an Image
inside it, then create a render method which creates a Bitmap
the size of the canvas, draws on it using a Graphics
object, then copies the output from a Bitmap
(which System.Drawing produces) to a BitmapImage
(which WPF can display).

Code
1. Add a Canvas
to your Window
Add a Canvas
to your layout and inside it include an Image
.
Add add a SizeChanged
method to your Window
and Loaded
and MouseDown
methods in your Canvas
. We will use these methods later to trigger renders.
<Grid>
<Canvas Name="myCanvas" MouseDown="myCanvas_MouseDown" Loaded="myCanvas_Loaded">
<Image Name="myImage"/>
</Canvas>
</Grid>
<Window ... SizeChanged="Window_SizeChanged">
2. Create a Method to Convert Bitmap
to BitmapImage
System.Drawing produces a Bitmap
but WPF can only display BitmapImage
objects. To facilitate converting between the two, add the following method to your source code.
private BitmapImage BmpImageFromBmp(Bitmap bmp)
{
using (var memory = new System.IO.MemoryStream())
{
bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
💡 NOTE: This method uses the PNG encoder to convert between formats to support transparency. Higher frame rates may be achieved using different encoders (at the expense of memory).
3. Create a Render()
Method
Here’s the star of the show! It’s nearly identical to the Windows Forms quickstart example, with key differences being:
- Bitmap size is determined by the
ActualWidth
andActualHeight
of theCanvas
- At the end of the render we copy the output to the
Source
property of anImage
.
Random rand = new Random();
private void Render()
{
using (var bmp = new Bitmap((int)myCanvas.ActualWidth, (int)myCanvas.ActualHeight))
using (var gfx = Graphics.FromImage(bmp))
using (var pen = new System.Drawing.Pen(System.Drawing.Color.White))
{
// draw one thousand random white lines on a dark blue background
gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
gfx.Clear(System.Drawing.Color.Navy);
for (int i = 0; i < 1000; i++)
{
var pt1 = new System.Drawing.Point(rand.Next(bmp.Width), rand.Next(bmp.Height));
var pt2 = new System.Drawing.Point(rand.Next(bmp.Width), rand.Next(bmp.Height));
gfx.DrawLine(pen, pt1, pt2);
}
myImage.Source = BmpImageFromBmp(bmp);
}
}
Call Render()
The Render method won’t run unless we tell it to. Let’s have it run when the program launches, when the window is resized, and when we click on the canvas.
private void myCanvas_Loaded(object sender, RoutedEventArgs e) => Render();
private void Window_SizeChanged(object sender, SizeChangedEventArgs e) => Render();
private void myCanvas_MouseDown(object sender, MouseButtonEventArgs e) => Render();
Improve this Application with Threading
This is a good start at drawing in a WPF application, but it has a flaw: calls to the render method block the GUI thread. This isn’t a problem if your renderer is very fast, but as it gets slow your GUI will become less responsive. A later article will demonstrate how to move the renderer into another thread so you can draw and animate graphics without blocking the GUI thread.