· 12 min read

How to Create a Blazor Chart — Step-by-Step Tutorial (2026)

Learn how to create charts in Blazor from scratch. This step-by-step tutorial covers SVG basics, chart libraries, and a complete walkthrough building line charts, bar charts, and interactive dashboards with Arcadia Controls.

BlazorChartsTutorial.NETSVGData Visualization

You want to add charts to your Blazor app. Maybe it is a dashboard for your SaaS product, an admin panel with analytics, or a reporting page for your enterprise app. But where do you start?

This tutorial covers everything — from rendering a raw SVG bar chart in Blazor with zero dependencies, to building a fully interactive multi-series line chart with tooltips, crosshairs, and real-time data. By the end, you will know exactly how Blazor chart components work and how to ship them to production.

Option 1: Build a Chart from Scratch with SVG

Before reaching for a library, it helps to understand how Blazor charts work under the hood. Every chart is ultimately SVG or Canvas. Here is a minimal bar chart in pure Blazor — no libraries, no JavaScript:

@page "/my-chart"

<svg width="400" height="200" viewBox="0 0 400 200">
    @foreach (var (label, value, index) in data.Select((d, i) => (d.Label, d.Value, i)))
    {
        var barHeight = value * 2;
        var x = index * 80 + 20;
        var y = 200 - barHeight;

        <rect x="@x" y="@y" width="60" height="@barHeight"
              fill="#8b5cf6" rx="4" />
        <text x="@(x + 30)" y="195" text-anchor="middle"
              fill="#9490b3" font-size="12">@label</text>
    }
</svg>

@code {
    private List<(string Label, double Value)> data = new()
    {
        ("Jan", 45), ("Feb", 72), ("Mar", 58), ("Apr", 88), ("May", 64)
    };
}

This renders five purple bars with labels. It works. But it has serious limitations:

Building all of that from scratch is hundreds of hours of work. That is why chart libraries exist.

Option 2: Use a Blazor Chart Library

A good chart library handles responsive layout, accessibility, tooltips, animations, axis formatting, and cross-browser rendering so you can focus on your data. Here is how the major Blazor chart libraries compare in 2026:

FeatureArcadia ControlsMudBlazorRadzenChartJs.Blazor
RenderingPure SVG (C#)SVG (JS interop)SVG (JS interop)Canvas (JS)
JS requiredNoYesYesYes (Chart.js)
Free chart types4688
Paid chart types16 totalN/A12+N/A
.NET 10YesYesYesNo
Auto render modeYesLimitedYesNo
AccessibilityWCAG 2.1 AAPartialPartialNone
Dashboard widgets7NoneSomeNone
Last updatedMarch 2026March 2026February 20262023

For this tutorial, we will use Arcadia Controls because it renders pure SVG from C# (no JavaScript to configure), supports every Blazor render mode, and has a free Community Edition.

Tutorial — Create a Line Chart with Arcadia Controls

Step 1: Create a new Blazor project

If you already have a Blazor project, skip to Step 2. Otherwise:

dotnet new blazor -n ChartDemo --interactivity Auto
cd ChartDemo

This creates a .NET 9+ Blazor project with Auto interactivity (server-side rendering with WebAssembly takeover).

Step 2: Install the Arcadia Charts package

dotnet add package Arcadia.Charts

The package targets .NET 5 through .NET 10, so it works regardless of your project’s target framework.

Step 3: Add the stylesheet

Open your App.razor (or _Host.cshtml for older Blazor Server projects) and add the CSS link in the <head>:

<link rel="stylesheet" href="_content/Arcadia.Charts/css/arcadia-charts.css" />

Step 4: Create a page with a basic line chart

Arcadia charts are strongly-typed generic components. You give the chart your data model, an XField accessor for the X-axis value, and a list of Series that say how to extract Y-values. Create a new file Components/Pages/Dashboard.razor:

@page "/dashboard"
@using Arcadia.Charts.Core
@using Arcadia.Charts.Components.Charts

<h1>Sales Dashboard</h1>

<ArcadiaLineChart TItem="MonthRevenue"
                  Data="@revenue"
                  XField="@(d => (object)d.Month)"
                  Series="@series"
                  Width="700"
                  Height="400"
                  XAxisTitle="Month"
                  YAxisTitle="Revenue ($k)"
                  ShowGrid="true" />

@code {
    record MonthRevenue(string Month, double Revenue);

    private List<MonthRevenue> revenue = new()
    {
        new("Jan", 32.1), new("Feb", 41.5), new("Mar", 38.7),
        new("Apr", 52.3), new("May", 61.8), new("Jun", 58.2),
        new("Jul", 67.4), new("Aug", 72.1), new("Sep", 69.8),
        new("Oct", 78.5), new("Nov", 85.3), new("Dec", 91.7),
    };

    private List<SeriesConfig<MonthRevenue>> series = new()
    {
        new() { Name = "Revenue", Field = d => d.Revenue, Color = "#8b5cf6" },
    };
}

Navigate to /dashboard and you will see a line chart with monthly revenue data. The chart renders as SVG — inspect the DOM and you will see <svg>, <path>, <circle>, and <text> elements. No <canvas>, no JavaScript runtime.

Step 5: Add multiple series

Real dashboards compare data. The chart already takes a List<SeriesConfig<T>>, so adding a second line is one entry in series:

<ArcadiaLineChart TItem="YearOverYear"
                  Data="@data"
                  XField="@(d => (object)d.Month)"
                  Series="@series"
                  Width="700"
                  Height="400"
                  XAxisTitle="Month"
                  YAxisTitle="Revenue ($k)"
                  ShowGrid="true"
                  ShowLegend="true" />

@code {
    record YearOverYear(string Month, double Y2025, double Y2026);

    private List<YearOverYear> data = new()
    {
        new("Jan", 32.1, 38.5), new("Feb", 41.5, 49.2),
        new("Mar", 38.7, 45.1), new("Apr", 52.3, 59.7),
        new("May", 61.8, 70.3), new("Jun", 58.2, 65.8),
        new("Jul", 67.4, 74.2), new("Aug", 72.1, 81.5),
        new("Sep", 69.8, 77.3),
    };

    private List<SeriesConfig<YearOverYear>> series = new()
    {
        new() { Name = "2025 Revenue", Field = d => d.Y2025, Color = "#8b5cf6" },
        new() { Name = "2026 Revenue", Field = d => d.Y2026, Color = "#ec4899" },
    };
}

The ShowLegend="true" parameter adds a color-coded legend so users can distinguish the series.

Step 6: Add area fill and smooth curves

Curve shape and area fill are per-series. Set CurveType = "smooth" for spline interpolation and ShowArea = true for the translucent fill beneath each line:

private List<SeriesConfig<YearOverYear>> series = new()
{
    new() { Name = "2025 Revenue", Field = d => d.Y2025, Color = "#8b5cf6",
            CurveType = "smooth", ShowArea = true, AreaOpacity = 0.15 },
    new() { Name = "2026 Revenue", Field = d => d.Y2026, Color = "#ec4899",
            CurveType = "smooth", ShowArea = true, AreaOpacity = 0.15 },
};

CurveType accepts "linear" (default), "smooth" (Catmull-Rom spline), or "step".

Step 7: Tooltips and crosshair

Tooltips are on by default for data points. To add a vertical crosshair that tracks the cursor and helps align values across series, set ShowCrosshair="true" on the chart:

<ArcadiaLineChart TItem="YearOverYear"
                  Data="@data"
                  XField="@(d => (object)d.Month)"
                  Series="@series"
                  Width="700"
                  Height="400"
                  XAxisTitle="Month"
                  YAxisTitle="Revenue ($k)"
                  ShowGrid="true"
                  ShowLegend="true"
                  ShowCrosshair="true"
                  YAxisFormatString="$#,##0.0k" />

YAxisFormatString controls how the Y-axis ticks (and the values inside default tooltips) are formatted.

Adding Interactivity

Click events

OnPointClick is a strongly-typed EventCallback<PointClickEventArgs<T>>. The Razor source generator sometimes has trouble inferring the type argument when binding a typed handler with a method group, so the safest pattern is the explicit factory shown below:

<ArcadiaLineChart TItem="MonthRevenue"
                  Data="@revenue"
                  XField="@(d => (object)d.Month)"
                  Series="@series"
                  Width="700"
                  Height="400"
                  OnPointClick="@(EventCallback.Factory.Create<PointClickEventArgs<MonthRevenue>>(this, HandlePointClick))" />

<p>Selected: @selectedPoint</p>

@code {
    private string selectedPoint = "Click a data point";

    private void HandlePointClick(PointClickEventArgs<MonthRevenue> args)
    {
        selectedPoint = $"{args.SeriesName}: {args.Value:C1} ({args.Item.Month})";
    }
}

PointClickEventArgs<T> carries the clicked item, its data index, the series name, and the Y-value.

Annotations and reference lines

Annotations are a parameter, not a child element. Pass a List<ChartAnnotation>:

<ArcadiaLineChart TItem="MonthRevenue"
                  Data="@revenue"
                  XField="@(d => (object)d.Month)"
                  Series="@series"
                  Annotations="@annotations"
                  Width="700"
                  Height="400"
                  ShowGrid="true" />

@code {
    private List<ChartAnnotation> annotations = new()
    {
        new ChartAnnotation
        {
            Type = ChartAnnotationType.HorizontalLine,
            Value = 70,
            Color = "#f59e0b",
            Label = "Target",
            StrokeDash = "6,4",
        },
    };
}

A dashed horizontal line at 70k is useful for KPI tracking, SLA thresholds, and budget targets.

Dynamic data updates

Charts automatically re-render when their parameters change. For real-time / streaming data, use an ObservableCollection<T> — the chart subscribes to INotifyCollectionChanged and re-renders without manual StateHasChanged calls:

@using System.Collections.ObjectModel

<ArcadiaLineChart TItem="Tick"
                  Data="@liveData"
                  XField="@(d => (object)d.Time)"
                  Series="@series"
                  Width="700"
                  Height="400" />

<button @onclick="AddTick">Add Point</button>

@code {
    record Tick(DateTime Time, double Value);

    private ObservableCollection<Tick> liveData = new();

    private List<SeriesConfig<Tick>> series = new()
    {
        new() { Name = "Live", Field = d => d.Value, Color = "#10b981", CurveType = "smooth" },
    };

    protected override void OnInitialized()
    {
        var t = DateTime.Now;
        for (int i = 0; i < 5; i++) liveData.Add(new Tick(t.AddSeconds(i), 10 + i * 3));
    }

    private void AddTick()
    {
        var last = liveData[^1];
        var rng = new Random();
        liveData.Add(new Tick(last.Time.AddSeconds(1), last.Value + rng.Next(-5, 8)));
    }
}

Creating Other Chart Types

Bar charts use the same Data + XField + Series pattern as line charts:

<ArcadiaBarChart TItem="QuarterRow"
                 Data="@quarters"
                 XField="@(d => (object)d.Region)"
                 Series="@barSeries"
                 Width="600"
                 Height="350"
                 ShowGrid="true" />

@code {
    record QuarterRow(string Region, double Q1, double Q2);

    private List<QuarterRow> quarters = new()
    {
        new("NA", 85, 92), new("EU", 72, 81),
        new("APAC", 91, 88), new("LATAM", 68, 75), new("MEA", 77, 83),
    };

    private List<SeriesConfig<QuarterRow>> barSeries = new()
    {
        new() { Name = "Q1", Field = d => d.Q1, Color = "#8b5cf6" },
        new() { Name = "Q2", Field = d => d.Q2, Color = "#ec4899" },
    };
}

Pie charts have a simpler shape — one NameField and one ValueField:

<ArcadiaPieChart TItem="DeviceShare"
                 Data="@devices"
                 NameField="@(d => d.Device)"
                 ValueField="@(d => d.Share)"
                 Width="400"
                 Height="400"
                 ShowLabels="true" />

@code {
    record DeviceShare(string Device, double Share);

    private List<DeviceShare> devices = new()
    {
        new("Desktop", 58.3), new("Mobile", 31.2), new("Tablet", 10.5),
    };
}

Going Further

This tutorial covered the fundamentals of creating Blazor charts. Here is where to go next:

More chart types:

Dashboard widgets:

Advanced features:

Tools:

Get Started Now

Install the free Community Edition and have your first chart rendering in under a minute:

dotnet add package Arcadia.Charts

The Community Edition includes Line, Bar, Pie, and Scatter charts — enough for most dashboards. When you need advanced visualizations like Treemaps, Heatmaps, or Candlestick charts, Pro starts at $299/developer/year.

Every chart in this tutorial works in Blazor Server, WebAssembly, and Auto render modes without any code changes. No JavaScript configuration required.

Ready to try Arcadia?

Start with the free Community edition — 4 chart types, sparklines, notifications, and a full theme engine.