# WPF Flowchart Diagram Shapes: Build Every Symbol in XAML

Canonical: https://sakura5.app/blog/wpf-flowchart-diagram-shapes/  
Published: 2026-10-30  
Author: the Sakura5 team · 8 min read  
Updated: 2026-10-30  
Publisher: Sakura5 (https://sakura5.app) · support@sakura5.app

> **TL;DR:** WPF flowchart diagram shapes, built in XAML: the geometry for every symbol, how to label and connect them, and a full invoice-approval example with coordinates.

![WPF Flowchart Diagram Shapes: Build Every Symbol in XAML](https://sakura5.app/img/blog/inline/wpf-flowchart-diagram-shapes-1.jpg)

WPF flowchart diagram shapes are built from the classes in *System.Windows.Shapes*: a *Rectangle* with *RadiusX* and *RadiusY* set to half its height makes the oval terminator, a plain *Rectangle* is a process step, a four-point *Polygon* is the decision diamond, and a *Path* with a short geometry string draws everything else — the parallelogram, the document, the database cylinder. You place them on a *Canvas*, put a *TextBlock* on top of each one, and draw the arrows yourself, because WPF has no built-in connector or arrowhead.

Drawing one diamond in XAML takes a line. Turning a dozen of them into a chart that stays readable and moves when you drag a node takes structure you have to decide on up front.

This guide covers why the obvious approach breaks down, the geometry for each standard shape, how to wrap the shapes so they carry a label and a position, a full worked example of an invoice-approval chart with real coordinates, the edge cases that cause blurry lines and misplaced arrows, and answers to the questions developers ask most.

## Why dropping shapes on a Canvas falls apart

The first instinct is to add shapes to a *Canvas* and set *Canvas.Left* and *Canvas.Top* by hand. It works for five nodes. By fifteen, three problems show up.

The first is text. A WPF *Shape* has no content property, so there is nowhere to put the label. You end up stacking a separate *TextBlock* at the same coordinates, and the moment you move one, the other stays behind.

The second is connectors. An arrow between two nodes needs to know where both nodes are. With literal coordinates in XAML, every move means editing the arrow too.

The third is meaning. Once shapes are scattered across markup, nothing enforces that a diamond is always a decision and a parallelogram is always input or output. A tidy chart depends on shapes meaning one thing each — the same rule covered in our guide to [flowchart symbols and meanings for beginners](https://sakura5.app/blog/flowchart-symbols-and-meanings-for-beginners/) — and hand-placed markup makes that rule easy to break.

## The geometry for each WPF flowchart diagram shape

Every shape below assumes a node box of 160 by 60 device-independent pixels. Set *Stretch="Fill"* on a *Path* if you want the same geometry to scale to whatever size the node is given.

![The geometry for each WPF flowchart diagram shape — wpf flowchart diagram shapes](https://sakura5.app/img/blog/inline/wpf-flowchart-diagram-shapes-2.jpg)

*Every shape below assumes a node box of 160 by 60 device-independent pixels.*

### 1. Terminator (start and end)

Use a *Rectangle* with *Width="160"*, *Height="60"*, *RadiusX="30"* and *RadiusY="30"*. Setting the radius to half the height gives the pill shape most charts use for start and end. An *Ellipse* also works but squeezes longer labels.

### 2. Process (a step or action)

A plain *Rectangle*, 160 by 60. Keep the corner radius at zero or a small value such as 4 so it never gets confused with the terminator.

### 3. Decision (yes or no)

A *Polygon* with *Points="80,0 160,30 80,60 0,30"*. Diamonds hold less text than rectangles of the same width, so many charts make the decision node taller, for example 160 by 80 with points “80,0 160,40 80,80 0,40”.

### 4. Input or output

A *Path* with *Data="M 20,0 L 160,0 L 140,60 L 0,60 Z"*. The 20-pixel offset sets the slant. Keep it the same across the whole chart so every parallelogram reads as the same symbol.

### 5. Document

A *Path* whose bottom edge is a Bezier curve: *Data="M 0,0 L 160,0 L 160,50 C 120,38 80,66 40,54 C 25,50 10,50 0,54 Z"*.

### 6. Database (stored data)

A cylinder built from two elliptical arcs: *Data="M 0,10 A 80,10 0 0 1 160,10 L 160,50 A 80,10 0 0 1 0,50 Z M 0,10 A 80,10 0 0 0 160,10"*. The second figure draws the visible front lip of the top ellipse. The path markup syntax for arcs and curves is documented in Microsoft’s [shapes and basic drawing overview for WPF](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/shapes-and-basic-drawing-in-wpf-overview), which is worth keeping open while you work.

## Wrapping shapes so they carry a label and a position

Raw shapes are the drawing layer. To make them behave like flowchart nodes, give each one a container that knows its text, its kind and its location.

### 1. Model the node, not the shape

Create a small view-model class with *Kind* (Terminator, Process, Decision, InputOutput, Document, Database), *Label*, *X*, *Y*, *Width* and *Height*. Connectors become a second class that holds a reference to a source node, a target node and an optional label such as “Yes.”

### 2. Render the list with an ItemsControl on a Canvas

Bind an *ItemsControl* to the node collection and set its *ItemsPanel* to a *Canvas*. Set *Canvas.Left* and *Canvas.Top* in the *ItemContainerStyle*, not in the item template. The template’s root sits inside a *ContentPresenter*, and only the presenter is a direct child of the Canvas, so attached properties set deeper in are ignored.

### 3. Pick the shape with a DataTemplateSelector or triggers

Each template is a *Grid* holding the shape and a centered *TextBlock* with *TextWrapping="Wrap"*. A *DataTemplateSelector* keyed on *Kind* chooses the right one. Because the label and the shape share one Grid, they can’t drift apart.

### 4. Draw connectors from node positions

Render connectors in a second *ItemsControl* layered underneath the nodes. Each connector is a *Path* whose geometry is computed from the source and target rectangles, plus a small filled triangle for the arrowhead. Recompute when either node’s X or Y changes, and the arrows follow every drag.

### 5. Plan the flow before writing XAML

The slowest part of building a chart in code is changing its structure after the coordinates are set, so settle the branches first. A tool like [Mindmap AI](https://sakura5.app/mindmapai/) is useful for that stage: type the process as a topic or paste a written description, and it lays the steps out as a map on an infinite canvas, where you can rearrange branches before you commit to coordinates.

## A worked example: an invoice-approval flowchart in WPF

Say you’re building an internal accounts-payable tool and the finance lead wants the approval rules shown as a chart inside the app. The process has nine nodes and one rule that matters: invoices over $5,000 need a manager’s sign-off.

![A worked example: an invoice-approval flowchart in WPF — wpf flowchart diagram shapes](https://sakura5.app/img/blog/inline/wpf-flowchart-diagram-shapes-3.jpg)

*The process has nine nodes and one rule that matters: invoices over $5,000 need a manager’s sign-off.*

The canvas is 600 pixels wide and the main column is centered at X = 220, so each 160-pixel node starts at Canvas.Left = 140. Nodes are spaced 100 pixels apart vertically.

- **Start** — terminator, “Invoice arrives by email,” at Y = 20.
- **Input** — parallelogram, “Clerk enters invoice data,” at Y = 120.
- **Process** — rectangle, “Match to purchase order,” at Y = 220.
- **Decision** — diamond, 160 by 80, “PO match found?” at Y = 320. The “No” branch goes right to a process node at X = 400, “Return to supplier,” which ends in its own terminator.
- **Decision** — diamond, “Amount over $5,000?” at Y = 440. “Yes” goes right to “Manager approves” at X = 400, Y = 440, then rejoins the main column.
- **Database** — cylinder, “Record in ledger,” at Y = 560.
- **Document** — “Generate payment file,” at Y = 660.
- **End** — terminator, “Invoice paid,” at Y = 760.

Built this way, the chart is one collection of nine node objects and nine connector objects. When the finance lead later asks to add a second threshold at $20,000 that requires a director, you insert one decision node and one process node into the collection, shift the nodes below by 120 pixels, and the connectors redraw themselves. No arrow is edited by hand.

One detail made it easier to read: connector labels sit at the midpoint of each arrow rather than beside the diamond, where they collided with the node text.

## Edge cases that trip up WPF flowcharts

### Blurry one-pixel strokes

Thin lines that land between physical pixels render soft and gray. Set *UseLayoutRounding="True"* on the root element, and consider *SnapsToDevicePixels="True"* on the shapes.

### Arrows that point at the box center

If a connector runs from center to center, its arrowhead ends up hidden under the target node. Clip the line to the target’s edge instead. For rectangles, intersect the line with the bounding box. For diamonds, intersect with the four edges of the polygon, or the arrowhead will float in empty space beside the corner.

### Dragging nodes

Put a *Thumb* in the node template and handle *DragDelta*, adding *HorizontalChange* and *VerticalChange* to the node’s X and Y. Because connectors bind to those properties, they follow automatically.

### Very large charts

Each *Shape* is a full *FrameworkElement* with layout and input handling. For a few dozen nodes this doesn’t matter. For something much larger and read-only, draw with *DrawingVisual* or a single *DrawingGroup* instead, and keep interactive elements only where users click.

If your chart is really a map of screens rather than a process, the shape vocabulary shifts slightly; our guide to [user flow diagram shapes](https://sakura5.app/blog/user-flow-diagram-shapes/) covers that version. And if you want to explore the structure of a flow before building it, [Mindmap AI](https://sakura5.app/mindmapai/) runs on iPhone, iPad and Mac, with the manual editor and outline view free.

## FAQ

**Does WPF have built-in flowchart shapes?**

No. WPF ships general-purpose shapes in System.Windows.Shapes — Rectangle, Ellipse, Line, Polyline, Polygon and Path — but no flowchart-specific controls or connectors. You build each flowchart symbol from those primitives, usually a Polygon for the diamond and a Path for the parallelogram, document and database shapes, then add labels and arrows yourself.

**How do I put text inside a WPF shape?**

Shapes have no content property, so place the shape and a TextBlock in the same Grid. The Grid sizes both to the same cell, and the TextBlock sits on top. Center it with HorizontalAlignment and VerticalAlignment, and set TextWrapping to Wrap so longer labels break onto two lines instead of overflowing the shape.

**How do I draw an arrow between two shapes in WPF?**

Use a Path whose geometry is a line from the edge of the source node to the edge of the target node, and add a small filled triangle at the end for the arrowhead. Compute both from the nodes’ positions in code or a converter, so the arrow redraws whenever either node moves or resizes.

**Should I use a third-party diagram library instead?**

If users need to build their own charts with palettes, snapping, routing and undo, a commercial or open-source diagramming control saves weeks. If your app only displays a known process, or you need a handful of interactive nodes, the built-in shapes on a Canvas are enough and add no dependency to maintain.

About the app: [MindMap AI: Mind Map Maker](https://sakura5.app/mindmapai/) · App Store: https://sakura5.app/go/mindmapai?from=/blog/wpf-flowchart-diagram-shapes/
