C#でチャートを作成する方法|初心者向けにグラフ表示・ライブラリ比較・実装手順を解説

はじめに

C#でチャートを作成すると、売上推移、月別集計、センサー値、アクセス数などの数値データを視覚的に表現できます。表だけでは把握しにくい変化や傾向も、折れ線グラフや棒グラフに変換すれば直感的に理解しやすくなります。

C#でチャートを表示する方法は、WinForms、WPF、ASP.NETなど、アプリケーションの種類によって異なります。また、標準のChartコントロールだけでなく、ScottPlot、OxyPlot、LiveChartsなどの外部ライブラリも利用できます。

この記事では、C#でチャートを作成する方法を初心者向けに解説します。Chartコントロールを使った基本的な実装手順から、ライブラリの比較、データ更新、エラー対処、画像保存まで順番に確認していきましょう。

1. C#でチャートを作成する前に知っておきたい基礎

1-1. C#のチャートとは?グラフ表示でできること

C#のチャートとは、数値や時系列データをグラフとして画面に表示するための機能です。主に次のような用途で使われます。

  • 日別・月別の売上推移を表示する

  • 商品別の販売数を比較する

  • 温度や湿度などのセンサー値を監視する

  • データベースの集計結果を可視化する

  • 複数のデータ系列を同じ画面で比較する

  • 分析結果を画像として保存する

たとえば、12か月分の売上を表だけで確認するより、折れ線グラフにしたほうが、売上が増えた月や減少傾向を把握しやすくなります。

C#では、画面上にグラフを表示するだけでなく、軸の範囲、目盛り、凡例、タイトル、色、線の太さなども細かく設定できます。

1-2. C#で作成できる主なグラフの種類

C#のチャート機能では、一般的に次のようなグラフを作成できます。

グラフの種類適した用途
折れ線グラフ時間による数値の変化
棒グラフ項目ごとの数値比較
円グラフ全体に対する割合
散布図2つの数値の関係
面グラフ推移と量の大きさの表現
積み上げ棒グラフ内訳を含む合計値の比較
バブルチャート3つの数値情報の比較
ローソク足チャート株価などの始値・高値・安値・終値
レーダーチャート複数評価項目のバランス比較

最初に作成するグラフとしては、設定項目が比較的少ない折れ線グラフか棒グラフがおすすめです。

1-3. WinForms・WPF・ASP.NETでチャート作成方法が異なる理由

C#で使用するチャート機能は、アプリケーションのUI技術によって異なります。

WinFormsは、Windows向けのデスクトップアプリを比較的簡単に作成できる技術です。.NET FrameworkのWinFormsでは、System.Windows.Forms.DataVisualization.Charting名前空間にあるChartコントロールを利用できます。Chartクラスでは、表示データを管理するSeriesと、軸や描画領域を管理するChartAreasが重要な役割を持ちます。Microsoft Learn+1

WPFは、XAMLを使って柔軟な画面デザインを作成できるデスクトップ向け技術です。標準で多機能なチャートコントロールが用意されているわけではないため、ScottPlot、OxyPlot、LiveChartsなどを導入する方法が一般的です。

ASP.NET CoreなどのWebアプリでは、C#は主にサーバー側でデータを取得・加工します。実際のグラフ描画は、ブラウザ上で動作するChart.jsやApache EChartsなどのJavaScriptライブラリに任せる構成がよく使われます。

1-4. 初心者が最初に選ぶべきチャート作成方法

初心者が選ぶ方法は、作成するアプリによって判断します。

.NET FrameworkのWinFormsアプリを学習している場合は、Chartコントロールから始めるとよいでしょう。Visual Studioのデザイナーを使って画面に配置でき、基本的な折れ線グラフや棒グラフを少ないコードで作成できます。

新しい.NETを使ったWinFormsやWPFアプリでは、ScottPlotが比較的導入しやすい選択肢です。アニメーションやモダンな画面表現を重視する場合はLiveCharts、MVVMとの組み合わせや柔軟なモデル設計を重視する場合はOxyPlotも候補になります。

Webアプリの場合は、C#だけで描画しようとせず、C#で作成したデータをJavaScriptチャートへ渡す方法を選ぶのが現実的です。

2. C#でチャートを作成する主な方法

2-1. 標準のChartコントロールを使う方法

.NET FrameworkのWinFormsでは、Chartコントロールをフォームに配置してグラフを作成できます。

基本的な構成要素は次の3つです。

  • ChartArea:軸や描画領域を管理する

  • Series:グラフに表示するデータ系列を管理する

  • Legend:系列名を示す凡例を管理する

デザイナーを使う方法だけでなく、C#コードからChartコントロールを生成することもできます。

C#
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

var chart = new Chart
{
Dock = DockStyle.Fill
};

chart.ChartAreas.Add(new ChartArea("MainArea"));

var series = new Series("売上")
{
ChartType = SeriesChartType.Line
};

series.Points.AddXY("1月", 120);
series.Points.AddXY("2月", 150);
series.Points.AddXY("3月", 135);

chart.Series.Add(series);
chart.Legends.Add(new Legend("MainLegend"));

Controls.Add(chart);
}
}

2-2. 外部ライブラリを使う方法

外部ライブラリを使うと、標準のChartコントロールにはない描画性能、アニメーション、操作機能、クロスプラットフォーム対応などを追加できます。

代表的なライブラリには次のものがあります。

  • ScottPlot

  • OxyPlot

  • LiveCharts

  • Syncfusion

  • DevExpress

  • Telerik

ScottPlotは、WinForms、WPF、WinUI、Blazorなどに対応し、大量データを扱うための機能も提供しています。公式サイトでは、折れ線、棒、円、散布図などを少ないコードで作成できるライブラリとして紹介されています。ScottPlot+1

外部ライブラリは、通常Visual StudioのNuGetパッケージマネージャーからインストールします。

2-3. WebアプリでJavaScriptチャートと連携する方法

ASP.NET CoreのWebアプリでは、C#で取得したデータをJSON形式に変換し、JavaScriptへ渡して描画します。

たとえば、コントローラーやRazor Pageで次のようなデータを作成します。

C#
public class SalesData
{
public string Month { get; set; } = string.Empty;
public decimal Amount { get; set; }
}

public IActionResult Index()
{
var sales = new List<SalesData>
{
new() { Month = "1月", Amount = 120000 },
new() { Month = "2月", Amount = 150000 },
new() { Month = "3月", Amount = 135000 }
};

return View(sales);
}

ビュー側では、モデルをJSONとしてJavaScriptへ渡します。

cshtml
@using System.Text.Json
@model List<SalesData>

<script>
const salesData = @Html.Raw(JsonSerializer.Serialize(Model));
const labels = salesData.map(item => item.Month);
const values = salesData.map(item => item.Amount);

// labelsとvaluesをJavaScriptチャートライブラリへ設定する
</script>

この構成では、データ取得や集計をC#が担当し、グラフ描画やマウス操作をJavaScriptが担当します。

2-4. 目的別に見るチャート作成方法の選び方

目的選択肢
.NET FrameworkのWinFormsで簡単に表示したいChartコントロール
新しい.NETのWinFormsで作成したいScottPlot、LiveCharts
WPFでMVVMを活用したいOxyPlot、LiveCharts
大量の時系列データを高速表示したいScottPlot
アニメーションを重視したいLiveCharts
Webブラウザに表示したいJavaScriptチャートとの連携
高度な帳票や業務サポートが必要商用ライブラリ

使用するライブラリを選ぶ前に、対応する.NETバージョン、UIフレームワーク、ライセンス、更新状況を確認しましょう。

3. C#のチャートライブラリ比較

3-1. Chartコントロールの特徴・メリット・デメリット

Chartコントロールは、.NET FrameworkのWinFormsで使いやすいグラフ表示機能です。

メリット

  • Visual Studioのデザイナーから配置できる

  • 基本的なグラフを少ないコードで作成できる

  • 折れ線、棒、円、散布図など多くの形式に対応している

  • DataTableやListなどをデータソースとして利用できる

  • 画像保存機能が用意されている

デメリット

  • 主に従来のWinFormsと.NET Frameworkを前提としている

  • WPFではそのまま利用できない

  • 大量データや高速更新では負荷が高くなりやすい

  • デザインを現代的に整えるには設定項目が多い

  • 新しい.NETでは標準の開発体験が.NET Frameworkと異なる

既存の.NET Framework製WinFormsアプリにグラフを追加する用途には適しています。

3-2. ScottPlotの特徴・メリット・デメリット

ScottPlotは、C#でグラフを作成できるオープンソースライブラリです。公式のクイックスタートでは、NuGetパッケージを導入し、数行のコードで散布図を表示・保存する手順が案内されています。WPFではScottPlot.WPFパッケージとWpfPlotコントロールを利用します。ScottPlot+1

メリット

  • 少ないコードでグラフを作成できる

  • 大量の数値データを扱いやすい

  • WinForms、WPF、Blazorなど複数の環境に対応している

  • 画像ファイルへの出力が簡単

  • サンプルが豊富

デメリット

  • バージョンによってAPIの書き方が変わる場合がある

  • 複雑な業務画面では追加の設計が必要

  • アニメーション表現はLiveChartsほど重視されていない

大量の測定データや時系列データを扱う場合に有力な選択肢です。

3-3. OxyPlotの特徴・メリット・デメリット

OxyPlotは、PlotModelに軸や系列を追加し、画面上のPlotViewへ設定する構成のチャートライブラリです。WPFでは、コードまたはXAMLからグラフの軸、系列、注釈などを定義できます。MITライセンスで公開され、プロプライエタリなソフトウェアでも利用可能と案内されています。OxyPlot+2OxyPlot+2

メリット

  • モデルとビューを分離しやすい

  • WPFやMVVMと組み合わせやすい

  • 軸や注釈を細かく設定できる

  • MITライセンスで利用できる

  • 描画部分を再利用しやすい

デメリット

  • 初心者にはPlotModelや系列クラスの構造が分かりにくい

  • 標準の見た目は比較的シンプル

  • ドキュメントの一部が古い場合があるため、対象パッケージのバージョン確認が必要

アプリ全体をMVVMで設計する場合や、グラフ設定をモデルとして管理したい場合に向いています。

3-4. LiveChartsの特徴・メリット・デメリット

LiveChartsは、アニメーションやインタラクティブな表現に強いチャートライブラリです。現行のLiveCharts2は複数の.NET向けUI環境に対応し、MITライセンスの無料機能と有料の選択肢が案内されています。LiveCharts+1

メリット

  • アニメーション付きのグラフを作成しやすい

  • モダンな見た目を実現しやすい

  • WPF、WinFormsなど複数の環境に対応している

  • データ更新を画面に反映しやすい

  • 円グラフやゲージなどの表示にも対応する

デメリット

  • アニメーションを多用すると処理負荷が高くなる場合がある

  • バージョンごとにパッケージ名や設定方法を確認する必要がある

  • SkiaSharpなどの依存関係を含む

  • 高速なリアルタイム描画では設定の調整が必要

見た目を重視したダッシュボードや、操作性の高い業務画面に向いています。

3-5. 商用ライブラリを使うべきケース

次のような要件がある場合は、商用ライブラリも検討しましょう。

  • 開発元による正式な技術サポートが必要

  • 複雑な金融チャートや統計グラフを使いたい

  • 印刷、PDF、Excel出力まで一括して実装したい

  • アクセシビリティや多言語対応が重要

  • 長期間運用する業務システムで継続的な更新が必要

  • 開発期間を短縮したい

商用ライブラリは費用がかかりますが、サンプル、デザイナー、サポート、関連UI部品が充実している場合があります。ライセンスが開発者単位なのか、アプリ配布単位なのかも確認が必要です。

3-6. 初心者におすすめのチャートライブラリ比較表

ライブラリ主な用途導入難易度大量データアニメーションおすすめ対象
Chartコントロール.NET Framework WinForms低い普通少ないWinForms初心者
ScottPlotWinForms・WPF・大量データ低い強い少ない実装を簡潔にしたい人
OxyPlotWPF・MVVM普通普通少ない設計を重視する人
LiveChartsダッシュボード・動的表示普通普通強い見た目を重視する人
商用ライブラリ高機能な業務システム製品による強い強いサポートが必要な企業

迷った場合は、.NET FrameworkのWinFormsならChartコントロール、新しい.NETのWinFormsやWPFならScottPlotから試すと理解しやすいでしょう。

4. C#のChartコントロールでグラフを表示する手順

4-1. Visual Studioでプロジェクトを作成する

Chartコントロールを使った基本例では、Visual Studioで「Windows フォーム アプリケーション(.NET Framework)」を作成します。

  1. Visual Studioを起動する

  2. 「新しいプロジェクトの作成」を選択する

  3. 「Windows フォーム アプリケーション(.NET Framework)」を選ぶ

  4. プロジェクト名を入力する

  5. 対象の.NET Frameworkを選択する

  6. 「作成」をクリックする

「Windows フォーム アプリ」と「Windows フォーム アプリケーション(.NET Framework)」は対象ランタイムが異なります。Chartコントロールを標準的な手順で使いたい場合は、プロジェクトテンプレートを間違えないようにしましょう。

4-2. Chartコントロールをフォームに追加する

プロジェクトを作成したら、Visual Studioのツールボックスを開きます。

  1. フォームのデザイナーを表示する

  2. 「表示」から「ツールボックス」を開く

  3. 「データ」カテゴリーを確認する

  4. 「Chart」をフォームへドラッグする

  5. プロパティから名前やサイズを設定する

以降のサンプルでは、フォーム上のChartコントロール名をchart1とします。

4-3. ChartArea・Series・Legendの基本を理解する

Chartコントロールでは、各要素に役割があります。

ChartArea

グラフを描画する領域です。X軸、Y軸、グリッド線、目盛り、表示範囲などを設定します。

Series

グラフに表示する1つのデータ系列です。「売上」「利益」「前年売上」のように、比較対象ごとにSeriesを作成します。

Legend

系列名を表示する凡例です。複数のSeriesを表示するときに、色とデータの関係を示します。

C#
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();

chart1.ChartAreas.Add(new ChartArea("MainArea"));
chart1.Legends.Add(new Legend("MainLegend"));

var series = new Series("売上")
{
ChartArea = "MainArea",
Legend = "MainLegend"
};

chart1.Series.Add(series);

デザイナーですでにChartAreaやSeriesを作成している場合は、同じ名前の要素を追加しないように注意してください。

4-4. 折れ線グラフを表示するサンプルコード

C#
using System.Windows.Forms.DataVisualization.Charting;

private void ShowLineChart()
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.Legends.Clear();

chart1.ChartAreas.Add(new ChartArea("MainArea"));
chart1.Legends.Add(new Legend("MainLegend"));

var series = new Series("売上")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
IsValueShownAsLabel = true
};

series.Points.AddXY("1月", 120);
series.Points.AddXY("2月", 150);
series.Points.AddXY("3月", 135);
series.Points.AddXY("4月", 180);
series.Points.AddXY("5月", 210);

chart1.Series.Add(series);
}

フォームのLoadイベントから呼び出します。

C#
private void Form1_Load(object sender, EventArgs e)
{
ShowLineChart();
}

折れ線グラフは、時間とともに変化する売上、温度、アクセス数などの表示に適しています。

4-5. 棒グラフを表示するサンプルコード

折れ線グラフとの主な違いは、ChartTypeColumnを指定する点です。

C#
private void ShowColumnChart()
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();

chart1.ChartAreas.Add(new ChartArea("MainArea"));

var series = new Series("販売数")
{
ChartType = SeriesChartType.Column,
IsValueShownAsLabel = true
};

series.Points.AddXY("商品A", 80);
series.Points.AddXY("商品B", 120);
series.Points.AddXY("商品C", 95);
series.Points.AddXY("商品D", 150);

chart1.Series.Add(series);
}

横向きの棒グラフにしたい場合は、SeriesChartType.Barを指定します。

4-6. 散布図を表示するサンプルコード

散布図では、X値とY値の両方に数値を設定します。

C#
private void ShowScatterChart()
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();

chart1.ChartAreas.Add(new ChartArea("MainArea"));

var series = new Series("測定値")
{
ChartType = SeriesChartType.Point,
MarkerStyle = MarkerStyle.Circle,
MarkerSize = 8
};

series.Points.AddXY(10, 15);
series.Points.AddXY(12, 18);
series.Points.AddXY(15, 20);
series.Points.AddXY(18, 28);
series.Points.AddXY(22, 30);

chart1.Series.Add(series);

chart1.ChartAreas["MainArea"].AxisX.Title = "測定値X";
chart1.ChartAreas["MainArea"].AxisY.Title = "測定値Y";
}

散布図は、身長と体重、広告費と売上など、2つの数値に相関関係があるか確認するときに使います。

5. C#チャートの見た目をカスタマイズする方法

5-1. グラフタイトルを設定する

ChartコントロールのTitlesコレクションへタイトルを追加します。

C#
chart1.Titles.Clear();
chart1.Titles.Add("月別売上推移");

フォントも設定できます。

C#
using System.Drawing;

var title = new Title("月別売上推移")
{
Font = new Font("Meiryo UI", 14, FontStyle.Bold)
};

chart1.Titles.Clear();
chart1.Titles.Add(title);

5-2. X軸・Y軸のラベルを設定する

軸のタイトルは、ChartAreaから設定します。

C#
var area = chart1.ChartAreas["MainArea"];

area.AxisX.Title = "月";
area.AxisY.Title = "売上金額";
area.AxisY.LabelStyle.Format = "#,0円";

日付をX軸に表示する場合は、SeriesのX値をDateTimeとして登録し、表示形式を指定します。

C#
series.XValueType = ChartValueType.DateTime;
area.AxisX.LabelStyle.Format = "MM/dd";

series.Points.AddXY(new DateTime(2026, 1, 1), 120);
series.Points.AddXY(new DateTime(2026, 1, 2), 135);

5-3. 凡例を表示・非表示にする

凡例を非表示にする場合は、次のように設定します。

C#
chart1.Legends[0].Enabled = false;

Series単位で凡例から除外することもできます。

C#
chart1.Series["売上"].IsVisibleInLegend = false;

複数系列を表示する場合は、凡例を表示しておくとデータを識別しやすくなります。

5-4. 線の色・太さ・マーカーを変更する

C#
using System.Drawing;

var series = chart1.Series["売上"];

series.Color = Color.SteelBlue;
series.BorderWidth = 3;
series.MarkerStyle = MarkerStyle.Circle;
series.MarkerSize = 8;
series.MarkerColor = Color.White;
series.MarkerBorderColor = Color.SteelBlue;
series.MarkerBorderWidth = 2;

色だけで系列を区別すると、印刷時や色覚特性によって判別しにくい場合があります。線種やマーカー形状も組み合わせると見やすくなります。

C#
series.BorderDashStyle = ChartDashStyle.Dash;
series.MarkerStyle = MarkerStyle.Square;

5-5. 軸の範囲・目盛り・単位を調整する

C#
var yAxis = chart1.ChartAreas["MainArea"].AxisY;

yAxis.Minimum = 0;
yAxis.Maximum = 300;
yAxis.Interval = 50;

データに応じて最大値を設定する場合は、余白を持たせます。

C#
double maxValue = chart1.Series["売上"]
.Points
.Max(point => point.YValues[0]);

chart1.ChartAreas["MainArea"].AxisY.Maximum =
Math.Ceiling(maxValue * 1.1 / 10) * 10;

値が大きい場合は、表示を千単位や万単位に変換すると読みやすくなります。

C#
chart1.ChartAreas["MainArea"].AxisY.LabelStyle.Format = "#,0";
chart1.ChartAreas["MainArea"].AxisY.Title = "売上金額(千円)";

5-6. 複数系列のデータを表示する

C#
chart1.Series.Clear();

var currentYear = new Series("今年")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3
};

var previousYear = new Series("前年")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
BorderDashStyle = ChartDashStyle.Dash
};

string[] months = { "1月", "2月", "3月", "4月" };
int[] currentValues = { 120, 150, 135, 180 };
int[] previousValues = { 110, 130, 145, 160 };

for (int i = 0; i < months.Length; i++)
{
currentYear.Points.AddXY(months[i], currentValues[i]);
previousYear.Points.AddXY(months[i], previousValues[i]);
}

chart1.Series.Add(currentYear);
chart1.Series.Add(previousYear);

複数系列を表示するときは、X軸の項目数や順番をそろえることが重要です。

6. C#チャートにデータを追加・更新する方法

6-1. 配列やListのデータをチャートに表示する

配列からデータを追加する例です。

C#
string[] labels = { "1月", "2月", "3月", "4月" };
double[] values = { 120, 150, 135, 180 };

var series = chart1.Series["売上"];
series.Points.Clear();

for (int i = 0; i < labels.Length; i++)
{
series.Points.AddXY(labels[i], values[i]);
}

オブジェクトのListを使う場合は、データ用クラスを作成すると管理しやすくなります。

C#
public class MonthlySales
{
public string Month { get; set; } = string.Empty;
public decimal Amount { get; set; }
}
C#
var sales = new List<MonthlySales>
{
new() { Month = "1月", Amount = 120000 },
new() { Month = "2月", Amount = 150000 },
new() { Month = "3月", Amount = 135000 }
};

var series = chart1.Series["売上"];
series.Points.Clear();

foreach (var item in sales)
{
series.Points.AddXY(item.Month, item.Amount);
}

6-2. DataTableのデータをチャートにバインドする

ChartコントロールのDataSourceには、DataTable、DataView、配列、List、データリーダーなどを設定できます。必要に応じてDataBindを呼び出してデータを反映します。Microsoft Learn+1

C#
using System.Data;

var table = new DataTable();
table.Columns.Add("Month", typeof(string));
table.Columns.Add("Amount", typeof(decimal));

table.Rows.Add("1月", 120000);
table.Rows.Add("2月", 150000);
table.Rows.Add("3月", 135000);

chart1.Series.Clear();

var series = new Series("売上")
{
ChartType = SeriesChartType.Column,
XValueMember = "Month",
YValueMembers = "Amount"
};

chart1.Series.Add(series);
chart1.DataSource = table;
chart1.DataBind();

列名を間違えるとデータが表示されないため、XValueMemberYValueMembersがDataTableの列名と一致しているか確認してください。

6-3. CSVファイルのデータを読み込んで表示する

次のようなCSVファイルを読み込む例を考えます。

Month,Amount
1月,120000
2月,150000
3月,135000

単純なCSVであれば、File.ReadLinesを使って1行ずつ読み込めます。ReadLinesはファイル全体を一度に配列へ読み込まず、列挙しながら処理できるため、大きなテキストファイルでもメモリ使用量を抑えやすい方法です。Microsoft Learn

C#
using System.Globalization;
using System.IO;

private void LoadCsv(string filePath)
{
var series = chart1.Series["売上"];
series.Points.Clear();

foreach (string line in File.ReadLines(filePath).Skip(1))
{
string[] columns = line.Split(',');

if (columns.Length < 2)
{
continue;
}

string month = columns[0].Trim();

if (decimal.TryParse(
columns[1],
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal amount))
{
series.Points.AddXY(month, amount);
}
}
}

値の中にカンマ、改行、引用符が含まれる本格的なCSVでは、単純なSplit(',')では正しく解析できません。その場合は、CSV解析に対応したライブラリを利用しましょう。

6-4. データベースの値をチャートに表示する

データベースから月別売上を取得し、チャートに表示する例です。

C#
using Microsoft.Data.SqlClient;
using System.Data;

private async Task LoadSalesAsync()
{
const string connectionString =
"Server=localhost;Database=SalesDb;Integrated Security=True;TrustServerCertificate=True;";

const string sql = """
SELECT SalesMonth, SUM(Amount) AS TotalAmount
FROM Sales
GROUP BY SalesMonth
ORDER BY SalesMonth
""";

var table = new DataTable();

await using var connection = new SqlConnection(connectionString);
await using var command = new SqlCommand(sql, connection);

await connection.OpenAsync();

await using var reader = await command.ExecuteReaderAsync();
table.Load(reader);

chart1.Series.Clear();

var series = new Series("売上")
{
ChartType = SeriesChartType.Column,
XValueMember = "SalesMonth",
YValueMembers = "TotalAmount"
};

chart1.Series.Add(series);
chart1.DataSource = table;
chart1.DataBind();
}

接続文字列をソースコードへ直接記述する方法は学習用に限り、本番環境では設定ファイルや安全なシークレット管理機能を利用してください。また、UIが固まらないようにデータベース処理は非同期化するのが基本です。

6-5. リアルタイムにチャートを更新する方法

WinFormsでは、System.Windows.Forms.TimerTickイベントを使って定期的にデータを追加できます。Windows FormsのTimerはUIスレッド上で動作するため、Tickイベント内で時間のかかる処理を行わないことが重要です。Microsoft Learn+1

C#
private readonly Random random = new();
private readonly System.Windows.Forms.Timer timer = new();
private int elapsedSeconds;

private void StartRealtimeChart()
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();

chart1.ChartAreas.Add(new ChartArea("MainArea"));

var series = new Series("センサー値")
{
ChartType = SeriesChartType.Line,
BorderWidth = 2
};

chart1.Series.Add(series);

timer.Interval = 1000;
timer.Tick += Timer_Tick;
timer.Start();
}

private void Timer_Tick(object? sender, EventArgs e)
{
double value = 20 + random.NextDouble() * 10;
var series = chart1.Series["センサー値"];

series.Points.AddXY(elapsedSeconds, value);
elapsedSeconds++;

const int maxPoints = 60;

while (series.Points.Count > maxPoints)
{
series.Points.RemoveAt(0);
}

chart1.ChartAreas["MainArea"].RecalculateAxesScale();
}

長時間動作させる場合は、表示するデータ数に上限を設けます。すべての測定値を保存する必要がある場合は、表示用データと保存用データを分けて管理しましょう。

7. C#チャート作成でよくあるエラーと解決方法

7-1. Chartコントロールがツールボックスに表示されない

Chartコントロールが表示されない場合は、最初にプロジェクトの種類を確認します。

.NET FrameworkのWinFormsプロジェクトでは、ツールボックスの「データ」カテゴリーに表示されることがあります。見つからない場合は、次の手順を試します。

  1. ツールボックスを右クリックする

  2. 「アイテムの選択」を開く

  3. 「.NET Framework コンポーネント」を選ぶ

  4. Chartにチェックを入れる

  5. OKをクリックする

プロジェクトが新しい.NET向けの「Windows フォーム アプリ」である場合、.NET Frameworkと同じChartコントロールが最初から表示されるとは限りません。ライブラリの追加や別のチャートライブラリの採用を検討してください。

7-2. System.Windows.Forms.DataVisualizationが見つからない

次のようなエラーが出ることがあります。

名前空間 'DataVisualization' が 'System.Windows.Forms' に存在しません

.NET Frameworkプロジェクトでは、参照が追加されているか確認します。

  1. ソリューションエクスプローラーで「参照」を右クリックする

  2. 「参照の追加」を選択する

  3. System.Windows.Forms.DataVisualizationを探す

  4. チェックを入れて追加する

コードの先頭には次のusingが必要です。

C#
using System.Windows.Forms.DataVisualization.Charting;

新しい.NETを対象とするプロジェクトでは、同じアセンブリが標準参照として提供されていないため、単純にusingを追加するだけでは解決しません。対象フレームワークに対応するパッケージを導入するか、ScottPlotなどへ切り替えます。

7-3. グラフが表示されないときの確認ポイント

グラフが表示されない場合は、次の項目を順番に確認します。

  • Chartコントロールのサイズが0になっていないか

  • ChartAreaが1つ以上存在するか

  • SeriesがChartへ追加されているか

  • Seriesにデータポイントが入っているか

  • ChartTypeが設定されているか

  • SeriesのEnabledtrue

  • 軸の最小値と最大値が逆転していないか

  • データバインド後にDataBindが必要ではないか

  • XValueMember、YValueMembersの列名が正しいか

  • NaNや無限大など無効な数値が含まれていないか

デバッグ時には、ポイント数を確認すると原因を絞り込みやすくなります。

C#
int pointCount = chart1.Series["売上"].Points.Count;
MessageBox.Show($"データ件数: {pointCount}");

7-4. 軸ラベルや目盛りが見づらいときの対処法

項目数が多いと、X軸ラベルが重なります。その場合はラベルを回転します。

C#
var axisX = chart1.ChartAreas["MainArea"].AxisX;

axisX.LabelStyle.Angle = -45;
axisX.Interval = 1;

一部だけ表示する方法もあります。

C#
axisX.Interval = 2;

横幅に対してデータ数が多すぎる場合は、Chartコントロール自体を広げるか、ズームやスクロールを有効にします。

C#
axisX.ScaleView.Zoomable = true;
axisX.ScrollBar.Enabled = true;
axisX.IsLabelAutoFit = true;

7-5. データ数が多いときに処理が重くなる原因と対策

データ数が増えると、すべての点の描画、マーカー、ラベル、アニメーションなどが負荷になります。

主な対策は次のとおりです。

  • 表示点数を制限する

  • 一定間隔でデータを間引く

  • 画面幅に合わせて集約する

  • マーカーを非表示にする

  • 各データポイントのラベルを非表示にする

  • 更新のたびにSeriesを作り直さない

  • 更新頻度を下げる

  • データ取得を非同期化する

  • 大量データ向けライブラリへ変更する

たとえば、10万件をそのまま表示する代わりに、100件ごとの平均値や最大・最小値へ集約します。

C#
var reducedData = sourceData
.Select((value, index) => new { value, index })
.GroupBy(item => item.index / 100)
.Select(group => group.Average(item => item.value))
.ToList();

ただし、異常値を監視するチャートでは平均化によってピークが消える可能性があります。用途に応じて最大値、最小値、中央値などを残しましょう。

8. C#チャート作成の実践例

8-1. 売上データを折れ線グラフで表示する

C#
private void ShowSalesTrend()
{
string[] months =
{
"1月", "2月", "3月", "4月", "5月", "6月",
"7月", "8月", "9月", "10月", "11月", "12月"
};

decimal[] sales =
{
120000, 135000, 128000, 150000,
165000, 172000, 180000, 176000,
190000, 210000, 225000, 240000
};

chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.Titles.Clear();

var area = new ChartArea("MainArea");
area.AxisX.Title = "月";
area.AxisY.Title = "売上金額";
area.AxisY.LabelStyle.Format = "#,0円";

chart1.ChartAreas.Add(area);
chart1.Titles.Add("年間売上推移");

var series = new Series("売上")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
MarkerStyle = MarkerStyle.Circle,
MarkerSize = 7
};

for (int i = 0; i < months.Length; i++)
{
series.Points.AddXY(months[i], sales[i]);
}

chart1.Series.Add(series);
}

8-2. 月別集計データを棒グラフで表示する

LINQを使って日別データを月別に集計する例です。

C#
public class Sale
{
public DateTime SoldAt { get; set; }
public decimal Amount { get; set; }
}
C#
private void ShowMonthlyTotals(List<Sale> sales)
{
var monthlyTotals = sales
.GroupBy(sale => new
{
sale.SoldAt.Year,
sale.SoldAt.Month
})
.Select(group => new
{
Label = $"{group.Key.Year}/{group.Key.Month:00}",
Total = group.Sum(sale => sale.Amount)
})
.OrderBy(item => item.Label)
.ToList();

chart1.Series.Clear();

var series = new Series("月別売上")
{
ChartType = SeriesChartType.Column,
IsValueShownAsLabel = true
};

foreach (var item in monthlyTotals)
{
series.Points.AddXY(item.Label, item.Total);
}

chart1.Series.Add(series);
}

集計処理とチャート表示処理を分けると、テストや機能変更がしやすくなります。

8-3. センサー値をリアルタイムチャートで表示する

センサー値を表示する場合は、画面更新のたびに実機へ同期アクセスするのではなく、取得処理と表示処理を分離します。

C#
private readonly Queue<(DateTime Time, double Value)> sensorBuffer = new();
private readonly object bufferLock = new();

private void AddSensorValue(double value)
{
lock (bufferLock)
{
sensorBuffer.Enqueue((DateTime.Now, value));

while (sensorBuffer.Count > 300)
{
sensorBuffer.Dequeue();
}
}
}

Timerではバッファの内容をコピーして表示します。

C#
private void RefreshSensorChart()
{
List<(DateTime Time, double Value)> snapshot;

lock (bufferLock)
{
snapshot = sensorBuffer.ToList();
}

var series = chart1.Series["センサー値"];
series.Points.Clear();
series.XValueType = ChartValueType.DateTime;

foreach (var item in snapshot)
{
series.Points.AddXY(item.Time, item.Value);
}

chart1.ChartAreas["MainArea"].AxisX.LabelStyle.Format = "HH:mm:ss";
}

このように分離すると、センサー通信が一時的に遅くなっても画面処理への影響を減らせます。

8-4. 複数データを1つのチャートで比較する

単位が異なるデータを同じチャートへ表示する場合は、第2Y軸を利用できます。

C#
var salesSeries = new Series("売上")
{
ChartType = SeriesChartType.Column,
YAxisType = AxisType.Primary
};

var rateSeries = new Series("利益率")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
YAxisType = AxisType.Secondary
};

string[] months = { "1月", "2月", "3月" };
double[] sales = { 120, 150, 135 };
double[] rates = { 12.5, 15.2, 13.8 };

for (int i = 0; i < months.Length; i++)
{
salesSeries.Points.AddXY(months[i], sales[i]);
rateSeries.Points.AddXY(months[i], rates[i]);
}

chart1.Series.Clear();
chart1.Series.Add(salesSeries);
chart1.Series.Add(rateSeries);

var area = chart1.ChartAreas["MainArea"];
area.AxisY.Title = "売上(万円)";
area.AxisY2.Enabled = AxisEnabled.True;
area.AxisY2.Title = "利益率(%)";
area.AxisY2.LabelStyle.Format = "0.0%";

rates12.5のような値を入れる場合、0.0%を指定すると1,250%と表示されます。12.5%として表示したいなら、0.125を登録するか、表示形式を0.0にして軸タイトルへ「%」を記載します。

8-5. 作成したチャートを画像として保存する

Chartコントロールには、グラフをファイルやストリームへ保存するSaveImageメソッドがあります。PNGなどの形式を指定して出力できます。Microsoft Learn+1

C#
chart1.SaveImage("sales-chart.png", ChartImageFormat.Png);

保存ダイアログを使う場合は次のように実装します。

C#
private void SaveChartImage()
{
using var dialog = new SaveFileDialog
{
Filter = "PNG画像|*.png|JPEG画像|*.jpg",
FileName = "chart.png"
};

if (dialog.ShowDialog() != DialogResult.OK)
{
return;
}

string extension = Path.GetExtension(dialog.FileName).ToLowerInvariant();

ChartImageFormat format =
extension == ".jpg" || extension == ".jpeg"
? ChartImageFormat.Jpeg
: ChartImageFormat.Png;

chart1.SaveImage(dialog.FileName, format);
}

画像の解像度を高くしたい場合は、保存前にChartコントロールのサイズを一時的に大きくするか、印刷・帳票出力に適したライブラリを検討します。

9. C#でチャートを作成するときの注意点

9-1. .NET Frameworkと.NETの対応状況を確認する

「C#で使える」という情報だけでライブラリを選ぶのではなく、対象のランタイムを確認する必要があります。

  • .NET Framework

  • .NET 6、.NET 8などの新しい.NET

  • Windows専用

  • クロスプラットフォーム対応

  • WinForms対応

  • WPF対応

  • ASP.NET Core・Blazor対応

特にSystem.Windows.Forms.DataVisualization.ChartingのMicrosoft公式APIドキュメントは、.NET Framework 4.8.1を対象として掲載されています。新しい.NETで同じ構成を採用する場合は、標準搭載を前提にせず、互換パッケージの条件や保守状況を確認してください。Microsoft Learn+1

9-2. 無料ライブラリと商用ライブラリの違い

無料ライブラリでも、一般的な折れ線、棒、円、散布図は十分に作成できます。ただし、無料だから無条件で利用できるとは限りません。

確認すべき項目は次のとおりです。

  • 商用利用が認められているか

  • 著作権表示が必要か

  • ソースコードの公開義務があるか

  • 再配布条件があるか

  • 有料機能との境界はどこか

  • 技術サポートが提供されるか

企業で利用する場合は、開発担当者だけで判断せず、最新のライセンス原文を確認することが重要です。

9-3. 保守性・更新頻度・ライセンスを確認する

ライブラリを導入すると、そのAPIや依存パッケージがアプリの一部になります。

採用前に次の点を確認しましょう。

  • 最近も更新されているか

  • 不具合報告に対応しているか

  • 利用者やサンプルが十分にあるか

  • 対象.NETのサポートが明記されているか

  • メジャーバージョン更新でAPIが大きく変わらないか

  • 長期運用に適したライセンスか

また、NuGetパッケージのバージョンを無条件で自動更新すると、API変更によってビルドできなくなる場合があります。更新前にリリースノートを確認し、テスト環境で動作を検証してください。

9-4. デスクトップアプリとWebアプリで選ぶべき構成

デスクトップアプリでは、C#用のチャートコントロールを画面へ直接配置できます。ローカルファイル、装置、社内データベースなどとの連携にも適しています。

Webアプリでは、次の構成が基本です。

  1. C#でデータベースから値を取得する

  2. 必要な単位で集計する

  3. APIやRazorを通じてJSONを出力する

  4. JavaScriptでチャートを描画する

  5. 必要に応じて一定間隔でデータを再取得する

Webアプリでサーバー側に画像を生成する方法もありますが、ブラウザ上の拡大、ツールチップ、系列切り替えなどを実装したい場合は、JavaScriptによる描画が適しています。

9-5. 初心者がつまずきやすいポイント

初心者がつまずきやすいのは、コードそのものより、プロジェクトやパッケージの違いです。

特に注意したいのは次の点です。

  • .NET Frameworkと新しい.NETを混同する

  • WinForms向けとWPF向けのパッケージを間違える

  • ライブラリの異なるメジャーバージョンのサンプルを使う

  • デザイナーで作成済みのSeriesをコードから重複追加する

  • X軸・Y軸の列名を間違える

  • 数値が文字列のままになっている

  • UIスレッド以外から直接チャートを更新する

  • すべてのデータにラベルやマーカーを表示して重くする

エラーが出たときは、使用中の.NETバージョン、パッケージ名、パッケージバージョン、対象UI技術を最初に確認しましょう。

10. C#チャート作成に関するよくある質問

10-1. C#で無料で使えるチャートライブラリは?

無料で利用できる代表的な選択肢には、ScottPlot、OxyPlot、LiveCharts2などがあります。また、.NET FrameworkのWinFormsではChartコントロールも利用できます。

ただし、無料ライブラリでも利用条件は異なります。商用利用や再配布を予定している場合は、導入時点のライセンスを必ず確認してください。

初心者が新しい.NETで試す場合はScottPlot、WPFでMVVMを使う場合はOxyPlot、アニメーションを重視する場合はLiveCharts2が候補になります。

10-2. WPFでチャートを作成するならどのライブラリがよい?

用途によって異なります。

  • 実装の分かりやすさを重視する:ScottPlot

  • MVVMとの組み合わせを重視する:OxyPlot

  • アニメーションやデザインを重視する:LiveCharts2

  • 高度な業務機能や正式サポートを重視する:商用ライブラリ

WPFで外部ライブラリを使う場合は、XAMLへ専用コントロールを配置し、コードビハインドまたはViewModelからデータを設定します。

10-3. リアルタイムグラフを作成するには?

Timerやバックグラウンド処理でデータを取得し、一定間隔でSeriesへ値を追加します。

実装時には次の点が重要です。

  • 画面更新頻度を必要以上に高くしない

  • 表示するポイント数に上限を設ける

  • 通信やファイル処理をUIスレッドで実行しない

  • UI更新はUIスレッドへ切り替えて実行する

  • 保存用データと表示用データを分ける

  • 大量データでは間引きや集約を行う

100ミリ秒ごとに値を取得しても、画面更新は500ミリ秒ごとにまとめて行うなど、取得頻度と描画頻度を分けると負荷を抑えられます。

10-4. Chartコントロールは.NET 6以降でも使える?

.NET Frameworkで提供されていたSystem.Windows.Forms.DataVisualization.Chartingは、.NET 6以降のWinFormsプロジェクトで同じように標準利用できるとは限りません。

互換パッケージを使う方法はありますが、Microsoft公式の.NET Framework版と同等のサポートやデザイナー機能が保証されているとは限らないため、パッケージの対応バージョンと更新状況を確認する必要があります。

新規開発で.NET 6以降を使う場合は、ScottPlot、OxyPlot、LiveCharts2など、対象ランタイムへの対応を明記しているライブラリも比較するとよいでしょう。

10-5. C#で作成したチャートをExcelに出力できる?

出力できます。主な方法は次の3つです。

  1. ChartコントロールをPNG画像として保存し、Excelへ貼り付ける

  2. 元データをExcelへ出力し、Excel側でグラフを作成する

  3. Excel操作ライブラリを使い、ワークブック内にグラフを生成する

見た目をそのまま残したい場合は画像として出力します。Excel上で数値やグラフを編集したい場合は、元データとExcelネイティブのグラフを作成する方法が適しています。

なお、ChartコントロールのSaveImageで保存できるのはチャート画像であり、編集可能なExcelグラフそのものではありません。

まとめ

C#でチャートを作成する方法は、アプリケーションの種類と利用する.NETによって異なります。

.NET FrameworkのWinFormsでは、標準のChartコントロールを使うことで、折れ線グラフや棒グラフを比較的簡単に作成できます。新しい.NETやWPFでは、ScottPlot、OxyPlot、LiveChartsなどの外部ライブラリが有力な選択肢です。Webアプリでは、C#でデータを取得・集計し、JavaScriptライブラリで描画する構成が適しています。

最初は少量の固定データで折れ線グラフを表示し、Series、ChartArea、軸、凡例の役割を理解しましょう。その後、ListやDataTable、CSV、データベースとの連携、リアルタイム更新、画像保存へ進むと、C#のチャート作成を段階的に習得できます。