FlowGraph.Core 0.3.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FlowGraph.Core --version 0.3.0
                    
NuGet\Install-Package FlowGraph.Core -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FlowGraph.Core" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FlowGraph.Core" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="FlowGraph.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FlowGraph.Core --version 0.3.0
                    
#r "nuget: FlowGraph.Core, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FlowGraph.Core@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FlowGraph.Core&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=FlowGraph.Core&version=0.3.0
                    
Install as a Cake Tool

FlowGraph

A node-based graph editor for .NET and Avalonia, inspired by React Flow.

NuGet .NET 9 Avalonia License: MIT

FlowGraph Demo

Features

Core

  • Pan & Zoom - Mouse wheel zoom, middle-click pan, configurable drag behavior
  • Node System - Draggable, resizable, selectable nodes with custom renderers
  • Edge Types - Bezier, Straight, Step, SmoothStep curves with arrow markers
  • Connection Validation - Custom rules for valid connections
  • Undo/Redo - Full command history with keyboard shortcuts
  • Clipboard - Copy, cut, paste, duplicate operations
  • Serialization - JSON save/load support

Components

  • FlowMinimap - Overview with viewport navigation
  • FlowControls - Zoom in/out/fit buttons panel
  • FlowBackground - Dots, lines, or cross patterns
  • NodeToolbar - Floating toolbar on node selection
  • FlowDiagnostics - Debug panel for development
  • FlowPanel - Positioned overlay panels (9 positions)

Advanced

  • Grouping - Collapsible node groups with nesting
  • Edge Routing - Orthogonal, bezier, and smart routing algorithms
  • Animations - Smooth viewport, node, edge, and group animations
  • State Machine - Clean input handling architecture
  • Edge Reconnection - Drag edge endpoints to reconnect

Installation

dotnet add package FlowGraph.Avalonia

Or via NuGet Package Manager:

Install-Package FlowGraph.Avalonia

Quick Start

1. Add namespaces to your AXAML

<Window xmlns:fg="using:FlowGraph.Avalonia"
        xmlns:fgc="using:FlowGraph.Avalonia.Controls">

2. Add FlowCanvas and components

<Panel>
    
    <fgc:FlowBackground x:Name="Background" Variant="Dots" Gap="20" />
    
    
    <fg:FlowCanvas x:Name="Canvas" Graph="{Binding MyGraph}" />
    
    
    <fgc:FlowPanel Position="BottomLeft" Margin="16">
        <fgc:FlowControls TargetCanvas="{Binding #Canvas}" />
    </fgc:FlowPanel>
    
    
    <fgc:FlowPanel Position="BottomRight" Margin="16">
        <fgc:FlowMinimap TargetCanvas="{Binding #Canvas}" />
    </fgc:FlowPanel>
    
    
    <fgc:NodeToolbar TargetCanvas="{Binding #Canvas}" Position="Top" Offset="12">
        <StackPanel Orientation="Horizontal" Spacing="4">
            <Button Content="Delete" Click="OnDelete" />
            <Button Content="Duplicate" Click="OnDuplicate" />
        </StackPanel>
    </fgc:NodeToolbar>
</Panel>

3. Create a graph in your ViewModel

using FlowGraph.Core;

public class MainViewModel
{
    public Graph MyGraph { get; }

    public MainViewModel()
    {
        MyGraph = new Graph();

        var inputNode = new Node
        {
            Type = "input",
            Position = new Point(100, 100),
            Outputs = [new Port { Id = "out", Type = "data" }]
        };

        var processNode = new Node
        {
            Type = "process",
            Position = new Point(300, 100),
            Inputs = [new Port { Id = "in", Type = "data" }],
            Outputs = [new Port { Id = "out", Type = "data" }]
        };

        var outputNode = new Node
        {
            Type = "output",
            Position = new Point(500, 100),
            Inputs = [new Port { Id = "in", Type = "data" }]
        };

        MyGraph.AddNode(inputNode);
        MyGraph.AddNode(processNode);
        MyGraph.AddNode(outputNode);

        MyGraph.AddEdge(new Edge
        {
            Source = inputNode.Id,
            Target = processNode.Id,
            SourcePort = "out",
            TargetPort = "in",
            Type = EdgeType.Bezier,
            MarkerEnd = EdgeMarker.Arrow
        });

        MyGraph.AddEdge(new Edge
        {
            Source = processNode.Id,
            Target = outputNode.Id,
            SourcePort = "out",
            TargetPort = "in",
            Type = EdgeType.Bezier,
            MarkerEnd = EdgeMarker.ArrowClosed
        });
    }
}

4. Connect the background (code-behind)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Background.TargetCanvas = Canvas;
    }
}

Configuration

var settings = new FlowCanvasSettings
{
    // Grid
    GridSize = 20,
    SnapToGrid = true,
    ShowGrid = true,
    
    // Zoom
    MinZoom = 0.1,
    MaxZoom = 4.0,
    ZoomStep = 0.1,
    
    // Nodes
    NodeWidth = 150,
    NodeHeight = 80,
    
    // Connections
    StrictConnectionDirection = true,
    ConnectionSnapDistance = 30,
    
    // Selection
    BoxSelectionMode = BoxSelectionMode.Intersect,
    
    // Viewport
    PanOnDrag = true,
    PanOnScroll = false,
    PanOnScrollSpeed = 1.0,
    ViewportBounds = new Rect(-1000, -1000, 3000, 3000),
    ViewportBoundsPadding = 100
};

canvas.Settings = settings;

Custom Node Renderers

Create custom node appearances by implementing INodeRenderer:

public class CustomNodeRenderer : DefaultNodeRenderer
{
    private static readonly IBrush CustomBackground = new SolidColorBrush(Color.Parse("#E3F2FD"));
    private static readonly IBrush CustomBorder = new SolidColorBrush(Color.Parse("#2196F3"));

    public override Control CreateNodeVisual(Node node, NodeRenderContext context)
    {
        var control = base.CreateNodeVisual(node, context);
        
        if (control is Border border)
        {
            border.Background = CustomBackground;
            border.BorderBrush = CustomBorder;
            border.CornerRadius = new CornerRadius(12);
        }
        
        return control;
    }

    protected override string GetDisplayText(Node node)
    {
        return node.Data as string ?? node.Type;
    }
}

// Register the renderer
canvas.NodeRenderers.Register("custom", new CustomNodeRenderer());

Connection Validation

Implement IConnectionValidator for custom connection rules:

public class TypeMatchValidator : IConnectionValidator
{
    public ValidationResult Validate(ConnectionContext context)
    {
        if (context.SourceNode.Id == context.TargetNode.Id)
            return ValidationResult.Invalid("Cannot connect to self");
            
        if (context.SourcePort.Type != context.TargetPort.Type)
            return ValidationResult.Invalid("Port types must match");
            
        return ValidationResult.Valid();
    }
}

canvas.ConnectionValidator = new TypeMatchValidator();

Events

canvas.SelectionChanged += (s, e) => 
{
    Console.WriteLine($"Selected: {e.SelectedNodes.Count} nodes, {e.SelectedEdges.Count} edges");
};

canvas.ViewportChanged += (s, e) => 
{
    Console.WriteLine($"Zoom: {e.Zoom:P0}, Offset: ({e.OffsetX:F0}, {e.OffsetY:F0})");
};

canvas.NodeDragStart += (s, e) => Console.WriteLine($"Started dragging {e.Nodes.Count} nodes");
canvas.NodeDragStop += (s, e) => Console.WriteLine($"Stopped dragging");

canvas.ConnectStart += (s, e) => Console.WriteLine($"Connection started from {e.SourceNode.Type}");
canvas.ConnectEnd += (s, e) => 
{
    if (e.WasCompleted)
        Console.WriteLine("Connection created!");
    else
        Console.WriteLine("Connection cancelled");
};

Keyboard Shortcuts

Shortcut Action
Delete / Backspace Delete selected
Ctrl+A Select all
Ctrl+C Copy
Ctrl+X Cut
Ctrl+V Paste
Ctrl+D Duplicate
Ctrl+Z Undo
Ctrl+Y / Ctrl+Shift+Z Redo
Ctrl+G Group selected
Ctrl+Shift+G Ungroup
Escape Deselect all / Cancel operation

Animations

// Viewport
canvas.FitToViewAnimated(duration: 0.5);
canvas.CenterOnNodeAnimated(node, duration: 0.3);
canvas.ZoomToAnimated(targetZoom: 1.5, duration: 0.2);

// Nodes
canvas.AnimateNodesTo(positions, duration: 0.3);
canvas.AnimateNodesAppear(nodes, duration: 0.3, stagger: 0.05);
canvas.AnimateNodesDisappear(nodes, duration: 0.2);
canvas.AnimateSelectionPulse(node);

// Edges
canvas.AnimateEdgePulse(edge, pulseCount: 3);
canvas.AnimateEdgeFadeIn(edge, duration: 0.3);
canvas.AnimateEdgeFadeOut(edge, duration: 0.3);
canvas.AnimateEdgeColor(edge, Colors.Red, duration: 0.5);

// Flow animation (continuous)
var animation = canvas.StartEdgeFlowAnimation(edge, speed: 50);
canvas.StopEdgeFlowAnimation(animation);

// Groups
canvas.AnimateGroupCollapse(groupId, duration: 0.5);
canvas.AnimateGroupExpand(groupId, duration: 0.5);

Serialization

using FlowGraph.Core.Serialization;

// Save/Load JSON
var json = GraphSerializer.Serialize(graph);
var graph = GraphSerializer.Deserialize(json);

// File operations
graph.SaveToFile("graph.json");
var graph = GraphExtensions.LoadFromFile("graph.json");

// Clone
var copy = graph.Clone();

Node Grouping

// Create groups
canvas.GroupSelected();
canvas.GroupSelected("My Group");

// Collapse/expand
canvas.ToggleGroupCollapse(groupId);
canvas.AnimateGroupCollapse(groupId, duration: 0.5);
canvas.AnimateGroupExpand(groupId, duration: 0.5);

// Manage nodes
canvas.GroupManager.AddNodeToGroup(groupId, nodeId);
canvas.GroupManager.RemoveNodeFromGroup(nodeId);
canvas.UngroupSelected();

Edge Routing

canvas.Settings.EnableEdgeRouting = true;
canvas.Settings.DefaultEdgeRouter = EdgeRouterType.Orthogonal;

// Available routers: Direct, Orthogonal, SmartBezier

canvas.Routing.RouteAllEdges();
canvas.Routing.RouteEdge(edgeId);

Project Structure

FlowGraph/
├── FlowGraph.Core           # Data models, commands, serialization
├── FlowGraph.Avalonia       # Avalonia UI controls and rendering
├── FlowGraph.Demo           # Sample application
└── FlowGraph.Core.Tests     # Unit tests

Requirements

  • .NET 9.0 or later
  • Avalonia 11.2 or later

Contributing

Contributions are welcome. Priority areas:

  • Documentation
  • Unit tests
  • Bug fixes
  • Performance improvements

License

MIT License - see LICENSE for details.

Acknowledgments

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on FlowGraph.Core:

Package Downloads
FlowGraph.Avalonia

A .NET/Avalonia node-based graph editor inspired by React Flow. Features include pan/zoom, node dragging, edge connections, grouping, minimap, animations, and more.

FlowGraph.3D

3D rendering capabilities for FlowGraph using OpenGL via Silk.NET. Provides hardware-accelerated 3D visualization for node-based graphs.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0 128 1/19/2026
0.7.0 109 1/17/2026
0.6.0 114 1/17/2026
0.5.1 113 1/16/2026
0.5.0 122 1/15/2026
0.4.2 113 1/14/2026
0.4.1 111 1/10/2026
0.4.0 109 1/10/2026
0.3.7 111 1/10/2026
0.3.4 111 1/9/2026
0.3.3 145 1/9/2026
0.3.2 118 1/9/2026
0.3.0 115 1/8/2026
0.2.2 126 1/8/2026
0.2.0 151 1/8/2026
0.1.0 122 1/6/2026