C# Charts入門:Chartコントロールでグラフを描画・リアルタイム表示する方法とライブラリ比較
はじめに
C#で業務アプリや分析ツールを作っていると、「売上推移を折れ線グラフで表示したい」「センサー値をリアルタイムに監視したい」「CSVやデータベースの集計結果をグラフ化したい」といった場面がよくあります。このような用途で検索されることが多いキーワードが「csharp charts」です。
C# Chartsといっても、選択肢は1つではありません。WinFormsで使える標準的なChartコントロール、WPF向けの外部ライブラリ、BlazorやWebアプリで使うJavaScript連携チャート、さらに大量データや高速リアルタイム描画に強い商用ライブラリまであります。
この記事では、C#でグラフを描画する基本から、Chartコントロールを使った折れ線グラフ・棒グラフ・円グラフ・散布図、リアルタイム表示、パフォーマンス対策、さらにLiveCharts2・ScottPlot・OxyPlot・Plotly.NETなどのライブラリ比較までまとめて解説します。
1. C# Chartsでできることと検索ユーザーが知りたい全体像
C#でChartsを使う目的は、大きく分けると「データを見やすくする」「変化を監視する」「分析結果を共有する」の3つです。単に数値を一覧表示するだけでは傾向が分かりにくい場合でも、折れ線グラフや棒グラフにすると、増減・分布・比較・異常値を直感的に把握できます。
たとえば、次のような用途でC#のChart機能が使われます。
売上・在庫・アクセス数などの集計結果を表示する業務アプリ、温度・電圧・圧力などのセンサー値をリアルタイムに表示する監視ツール、CSVやログファイルを読み込んで可視化する解析ツール、株価やCPU使用率など時間変化するデータを追跡するダッシュボード、検査結果や測定値を散布図・ヒストグラムで確認する品質管理システムなどです。
C# Chartsを学ぶときは、最初から高機能なライブラリを選ぶよりも、まず「どのアプリ形態で、どの程度のデータ量を、どのくらいの更新頻度で表示するのか」を整理することが重要です。
1-1. C#でグラフを描画する代表的な方法
C#でグラフを描画する方法は、主に次の4種類です。
1つ目は、WinFormsのChartコントロールを使う方法です。System.Windows.Forms.DataVisualization.Charting名前空間に含まれるChartコントロールを使うと、折れ線グラフ、棒グラフ、円グラフ、散布図などを比較的少ないコードで表示できます。Microsoftのドキュメントでも、ChartクラスはWindows Forms用Chartコントロールのプロパティ・メソッド・イベントを公開するクラスとして説明されています。
2つ目は、ScottPlotやLiveCharts2、OxyPlotなどの外部ライブラリを使う方法です。これらはNuGetから導入でき、標準Chartコントロールよりも見た目・操作性・パフォーマンス・クロスプラットフォーム対応に優れる場合があります。
3つ目は、Plotly.NETやPlotly.Blazor、Chart.js連携などWeb系チャートを使う方法です。ASP.NET CoreやBlazorでダッシュボードを作る場合は、ブラウザ上で動くインタラクティブなチャートが向いています。
4つ目は、LightningChart、TeeChart、DevExpress、SciChartなどの商用ライブラリを使う方法です。大量データ、高速リアルタイム描画、3D表示、金融チャート、産業用途などでは商用ライブラリを検討する価値があります。
1-2. Chartコントロール・外部ライブラリ・Web系チャートの違い
Chartコントロールは、WinFormsで手軽にグラフを表示したい場合に便利です。Visual Studioのフォームデザイナーに配置して、Seriesにデータを追加するだけでグラフを描画できます。学習コストが低く、社内ツールや小規模アプリでは今でも使いやすい選択肢です。
外部ライブラリは、より美しい見た目、軽快な操作、拡大縮小、リアルタイム描画、MVVM対応などを求める場合に向いています。たとえばScottPlotは、.NET向けの無料オープンソース描画ライブラリで、大量データをインタラクティブに表示しやすいことを特徴としています。
Web系チャートは、ブラウザで閲覧するダッシュボードや社内Webアプリに向いています。Plotly.NETは、plotly.jsのチャートを.NETから生成・レンダリングするためのライブラリとして提供されています。
つまり、C# Chartsの選び方は「デスクトップアプリかWebアプリか」「リアルタイム性が必要か」「無料でよいか商用でもよいか」「データ量がどの程度か」で決まります。
1-3. WinForms・WPF・ASP.NET・Blazorで選ぶべき実装方針
WinFormsで学習用や小規模ツールを作るなら、まずChartコントロールから始めるのがおすすめです。コード量が少なく、折れ線グラフ・棒グラフ・円グラフなどをすぐに表示できます。
WinFormsで高品質なグラフや大量データを扱いたい場合は、ScottPlotが候補になります。ScottPlotのWinFormsクイックスタートでは、ScottPlot.WinFormsのNuGetパッケージを追加し、FormsPlotをフォームに配置して使う流れが紹介されています。
WPFでMVVM構成、データバインディング、アニメーション、モダンなUIを重視するならLiveCharts2が向いています。LiveCharts2は.NET向けのデータ可視化ライブラリで、複数のデバイスやフレームワークで動作し、MITライセンスの無料版と有料版が提供されています。
ASP.NET CoreやBlazorでWebダッシュボードを作るなら、Plotly.NET、Plotly.Blazor、Chart.js連携などを検討します。ブラウザ上でツールチップ、ズーム、凡例クリック、レスポンシブ表示を使いたい場合はWeb系チャートが便利です。
1-4. この記事で作るサンプルとゴール
この記事では、主にWinFormsのChartコントロールを使って以下の内容を実装します。
折れ線グラフ、棒グラフ、円グラフ、散布図、複数系列グラフ、配列・List・Dictionary・DataTable・CSV・データベースからの描画、日付時刻をX軸にしたグラフ、Timerを使ったリアルタイム折れ線グラフ、最新100件だけ表示する処理、開始・停止ボタン付きの簡単な監視アプリです。
最終的には、C#でグラフを描画する基本を理解し、自分の用途に合わせて標準Chartコントロールと外部ライブラリを選べる状態を目指します。
2. C#標準のChartコントロールとは
C#のChartコントロールは、WinFormsアプリでグラフを描画するための代表的なコントロールです。フォーム上に配置し、ChartArea、Series、Legendなどを設定することで、さまざまなグラフを表示できます。
標準Chartコントロールは、特に「まずC#でグラフを表示してみたい」「社内向けの簡単な可視化ツールを作りたい」「.NET Frameworkの既存WinFormsアプリにグラフを追加したい」というケースで役立ちます。
2-1. System.Windows.Forms.DataVisualization.Chartingの概要
Chartコントロールを使うには、次の名前空間を使用します。
C#using System.Windows.Forms.DataVisualization.Charting;
System.Windows.Forms.DataVisualization.Charting名前空間には、Windows Forms用Chartコントロールのメソッドやプロパティが含まれています。
代表的なクラスは次のとおりです。
C#Chart
ChartArea
Series
Legend
Title
DataPoint
Axis
Chartはグラフ全体、ChartAreaは描画領域、Seriesはデータ系列、Legendは凡例、AxisはX軸・Y軸を表します。
2-2. Chart・ChartArea・Series・Legendの基本構造
Chartコントロールの構造は、次のように考えると分かりやすいです。
Chart
├─ ChartAreas
│ └─ ChartArea
│ ├─ AxisX
│ └─ AxisY
├─ Series
│ ├─ Series A
│ └─ Series B
├─ Legends
│ └─ Legend
└─ Titles
└─ Title
MicrosoftのChartクラスの説明でも、重要なプロパティとしてSeriesとChartAreasが挙げられており、Seriesは表示データと属性を格納し、ChartAreasは軸セットを使ってグラフを描画する領域を格納すると説明されています。
基本的な初期化コードは次のようになります。
C#chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.Titles.Clear();
var area = new ChartArea("MainArea");
chart1.ChartAreas.Add(area);
var series = new Series("売上")
{
ChartType = SeriesChartType.Line,
ChartArea = "MainArea"
};
chart1.Series.Add(series);
chart1.Legends.Add(new Legend("Legend"));
chart1.Titles.Add("月別売上");
2-3. Chartコントロールで作れるグラフの種類
Chartコントロールでは、SeriesChartTypeを変更することでさまざまな種類のグラフを作成できます。
代表的な種類は以下です。
C#SeriesChartType.Line // 折れ線グラフ
SeriesChartType.Column // 縦棒グラフ
SeriesChartType.Bar // 横棒グラフ
SeriesChartType.Pie // 円グラフ
SeriesChartType.Point // 散布図
SeriesChartType.Area // 面グラフ
SeriesChartType.Spline // 曲線グラフ
SeriesChartType.Doughnut // ドーナツグラフ
SeriesChartType.Candlestick // ローソク足
売上推移なら折れ線グラフ、カテゴリ比較なら棒グラフ、構成比なら円グラフ、相関を見たいなら散布図が向いています。
2-4. 標準Chartコントロールが向いているケース・向かないケース
Chartコントロールが向いているのは、.NET FrameworkのWinFormsアプリ、学習用サンプル、社内向け小規模ツール、数百〜数千点程度のデータ表示、単純な折れ線・棒・円グラフなどです。
一方で、WPFでMVVMにきれいに統合したい場合、大量データを高速に描画したい場合、なめらかなアニメーションやモダンなUIが必要な場合、Webブラウザで表示したい場合、GPUアクセラレーションや高度なリアルタイム描画が必要な場合は、外部ライブラリの利用を検討した方がよいです。
また、.NET 6や.NET 8のWinFormsで使う場合は注意が必要です。従来のChartコントロールは.NET Framework向けの文脈で使われることが多く、.NET 6以降では標準でそのまま使えるとは限りません。NuGetには、.NET FrameworkのSystem.Windows.Forms.DataVisualizationを継続する形で.NET 6+対応をうたうWinForms.DataVisualizationパッケージもあります。
3. C# Chartコントロールの基本設定
Chartコントロールを使う流れは、フォームに配置し、ChartAreaを作成し、Seriesを追加し、データを入れる、という順番です。
3-1. Visual StudioでChartコントロールを追加する方法
.NET FrameworkのWinFormsプロジェクトでは、Visual StudioのツールボックスからChartコントロールをフォームにドラッグして配置できます。
手順は次のとおりです。
Visual StudioでWindows Forms Appを作成します。フォームデザイナーを開きます。ツールボックスから「Chart」を探します。Chartをフォームにドラッグします。プロパティでNameをchart1などにします。フォームのロードイベントで初期化コードを書きます。
ツールボックスにChartが表示されない場合は、プロジェクトの種類やターゲットフレームワークを確認してください。.NET Frameworkでは使えても、.NET 6や.NET 8のWinFormsでは追加パッケージや別ライブラリが必要になることがあります。
3-2. NuGet・参照設定・名前空間の確認
.NET FrameworkのWinFormsでは、通常は参照設定にSystem.Windows.Forms.DataVisualizationを追加します。
コード側では次を追加します。
C#using System.Windows.Forms.DataVisualization.Charting;
.NET 6以降で標準Chart相当のコントロールを使いたい場合は、NuGetでWinForms.DataVisualizationなどの対応パッケージを検討します。ただし、プロジェクトの種類、ターゲットフレームワーク、ライセンス、メンテナンス状況を確認してから採用してください。
新規開発で迷う場合は、WinFormsならScottPlot、WPFならLiveCharts2やOxyPlot、WebならPlotly系を最初から選ぶ方がスムーズなこともあります。
3-3. フォームにChartを配置して初期化する
以下は、Chartコントロールを初期化する基本コードです。
C#private void Form1_Load(object sender, EventArgs e)
{
InitializeChart();
}
private void InitializeChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.Titles.Clear();
var area = new ChartArea("MainArea");
chart1.ChartAreas.Add(area);
var legend = new Legend("MainLegend");
chart1.Legends.Add(legend);
chart1.Titles.Add("サンプルグラフ");
var series = new Series("データ")
{
ChartType = SeriesChartType.Line,
ChartArea = "MainArea",
Legend = "MainLegend"
};
chart1.Series.Add(series);
}
この状態ではまだデータがないため、グラフは表示されません。次にPoints.AddXY()でデータを追加します。
C#chart1.Series["データ"].Points.AddXY(1, 10);
chart1.Series["データ"].Points.AddXY(2, 25);
chart1.Series["データ"].Points.AddXY(3, 18);
chart1.Series["データ"].Points.AddXY(4, 32);
3-4. X軸・Y軸・タイトル・凡例を設定する
軸や凡例を設定すると、グラフの意味が分かりやすくなります。
C#var area = chart1.ChartAreas["MainArea"];
area.AxisX.Title = "月";
area.AxisY.Title = "売上";
area.AxisX.MajorGrid.Enabled = false;
area.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dot;
chart1.Titles.Clear();
chart1.Titles.Add("月別売上推移");
chart1.Legends["MainLegend"].Docking = Docking.Bottom;
軸ラベルが重なる場合は、ラベル角度を変更します。
C#area.AxisX.LabelStyle.Angle = -45;
数値の範囲を固定したい場合は、MinimumとMaximumを設定します。
C#area.AxisY.Minimum = 0;
area.AxisY.Maximum = 100;
4. C#で基本グラフを描画する方法
ここからは、C# Chartコントロールでよく使う基本グラフのサンプルコードを紹介します。
4-1. 折れ線グラフを描画するサンプルコード
折れ線グラフは、時系列データや連続的な変化を表示するのに向いています。
C#private void DrawLineChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
var area = new ChartArea("MainArea");
area.AxisX.Title = "月";
area.AxisY.Title = "売上";
chart1.ChartAreas.Add(area);
var series = new Series("売上")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
ChartArea = "MainArea"
};
series.Points.AddXY("1月", 120);
series.Points.AddXY("2月", 150);
series.Points.AddXY("3月", 130);
series.Points.AddXY("4月", 180);
series.Points.AddXY("5月", 220);
chart1.Series.Add(series);
}
Seriesオブジェクトはデータ系列を表し、DataPointを格納します。MicrosoftのSeriesクラスの説明でも、Seriesはデータ系列を表し、DataPointを格納するものとされています。
4-2. 棒グラフを描画するサンプルコード
棒グラフは、カテゴリごとの比較に向いています。
C#private void DrawColumnChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("販売数")
{
ChartType = SeriesChartType.Column,
ChartArea = "MainArea"
};
series.Points.AddXY("商品A", 35);
series.Points.AddXY("商品B", 52);
series.Points.AddXY("商品C", 28);
series.Points.AddXY("商品D", 44);
chart1.Series.Add(series);
chart1.ChartAreas["MainArea"].AxisX.Title = "商品";
chart1.ChartAreas["MainArea"].AxisY.Title = "販売数";
}
横棒グラフにしたい場合は、SeriesChartType.Barを使います。
C#series.ChartType = SeriesChartType.Bar;
4-3. 円グラフを描画するサンプルコード
円グラフは、全体に対する割合を見せたい場合に便利です。
C#private void DrawPieChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
chart1.Legends.Add(new Legend("Legend"));
var series = new Series("構成比")
{
ChartType = SeriesChartType.Pie,
ChartArea = "MainArea",
Legend = "Legend",
IsValueShownAsLabel = true
};
series.Points.AddXY("Web", 45);
series.Points.AddXY("店舗", 30);
series.Points.AddXY("代理店", 15);
series.Points.AddXY("その他", 10);
series.Label = "#PERCENT{P1}";
series.LegendText = "#VALX";
chart1.Series.Add(series);
}
円グラフでは、項目数が多すぎると読みにくくなります。5項目程度までにまとめ、細かい分類は「その他」に集約すると見やすくなります。
4-4. 散布図を描画するサンプルコード
散布図は、2つの数値の関係を確認するのに向いています。
C#private void DrawScatterChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
var area = new ChartArea("MainArea");
area.AxisX.Title = "広告費";
area.AxisY.Title = "売上";
chart1.ChartAreas.Add(area);
var series = new Series("店舗データ")
{
ChartType = SeriesChartType.Point,
MarkerSize = 8,
ChartArea = "MainArea"
};
series.Points.AddXY(10, 120);
series.Points.AddXY(15, 160);
series.Points.AddXY(20, 180);
series.Points.AddXY(25, 210);
series.Points.AddXY(30, 260);
chart1.Series.Add(series);
}
散布図は、広告費と売上、温度と消費電力、年齢と購入金額など、相関を見たいデータに適しています。
4-5. 複数系列のデータを表示する方法
複数系列を表示すると、複数のデータを同じグラフ上で比較できます。
C#private void DrawMultipleSeries()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
chart1.Legends.Add(new Legend("Legend"));
var tokyo = new Series("東京")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
ChartArea = "MainArea",
Legend = "Legend"
};
var osaka = new Series("大阪")
{
ChartType = SeriesChartType.Line,
BorderWidth = 3,
ChartArea = "MainArea",
Legend = "Legend"
};
tokyo.Points.AddXY("1月", 8);
tokyo.Points.AddXY("2月", 10);
tokyo.Points.AddXY("3月", 14);
osaka.Points.AddXY("1月", 9);
osaka.Points.AddXY("2月", 11);
osaka.Points.AddXY("3月", 15);
chart1.Series.Add(tokyo);
chart1.Series.Add(osaka);
}
複数系列を使う場合は、凡例を表示し、系列名を分かりやすくすることが重要です。
5. データをChartに反映する実装パターン
実際のアプリでは、コードに直接AddXY()を書くよりも、配列、List、Dictionary、CSV、DataTable、データベースなどから取得したデータをChartに反映することが多くなります。
5-1. 配列・List・Dictionaryからグラフを作成する
配列から折れ線グラフを作る例です。
C#private void DrawFromArray()
{
int[] values = { 10, 25, 18, 40, 32 };
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("値")
{
ChartType = SeriesChartType.Line,
ChartArea = "MainArea"
};
for (int i = 0; i < values.Length; i++)
{
series.Points.AddXY(i + 1, values[i]);
}
chart1.Series.Add(series);
}
List<T>を使う場合は、データクラスを作ると管理しやすくなります。
C#public class SalesData
{
public string Month { get; set; } = "";
public int Amount { get; set; }
}
private void DrawFromList()
{
var list = new List<SalesData>
{
new SalesData { Month = "1月", Amount = 120 },
new SalesData { Month = "2月", Amount = 150 },
new SalesData { Month = "3月", Amount = 180 }
};
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("売上")
{
ChartType = SeriesChartType.Column
};
foreach (var item in list)
{
series.Points.AddXY(item.Month, item.Amount);
}
chart1.Series.Add(series);
}
Dictionaryは、カテゴリ名と値の対応を扱うときに便利です。
C#var data = new Dictionary<string, int>
{
{ "A", 30 },
{ "B", 45 },
{ "C", 20 }
};
foreach (var item in data)
{
series.Points.AddXY(item.Key, item.Value);
}
5-2. DataTableやCSVデータをChartにバインドする
DataTableを使うと、データベースやCSVから読み込んだデータを扱いやすくなります。
C#private void DrawFromDataTable()
{
var table = new DataTable();
table.Columns.Add("Month", typeof(string));
table.Columns.Add("Sales", typeof(int));
table.Rows.Add("1月", 120);
table.Rows.Add("2月", 150);
table.Rows.Add("3月", 180);
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("売上")
{
ChartType = SeriesChartType.Column,
XValueMember = "Month",
YValueMembers = "Sales"
};
chart1.Series.Add(series);
chart1.DataSource = table;
chart1.DataBind();
}
CSVを読み込む場合は、1行ずつ分割してDataTableまたはList<T>に変換してからChartに渡すと実装しやすいです。
C#private void DrawFromCsv(string path)
{
var lines = File.ReadAllLines(path);
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("CSVデータ")
{
ChartType = SeriesChartType.Line
};
foreach (var line in lines.Skip(1))
{
var columns = line.Split(',');
string label = columns[0];
double value = double.Parse(columns[1]);
series.Points.AddXY(label, value);
}
chart1.Series.Add(series);
}
実運用では、CSVの文字コード、カンマを含む値、空行、数値変換エラーに対応するため、CSVライブラリの利用も検討してください。
5-3. データベースの取得結果をグラフ化する
データベースの集計結果をグラフ化する場合は、SQLで集計してからChartに渡すと効率的です。
C#private void DrawFromDatabase(DataTable table)
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();
chart1.ChartAreas.Add(new ChartArea("MainArea"));
var series = new Series("売上")
{
ChartType = SeriesChartType.Line,
XValueMember = "SalesDate",
YValueMembers = "Amount"
};
chart1.Series.Add(series);
chart1.DataSource = table;
chart1.DataBind();
chart1.ChartAreas["MainArea"].AxisX.LabelStyle.Format = "MM/dd";
}
SQL側で日別・月別・カテゴリ別に集計しておくと、C#側の処理が軽くなります。大量データをそのままChartに渡すのではなく、表示に必要な粒度まで集約してから描画するのが基本です。
5-4. 日付・時刻データをX軸に表示する
日付や時刻をX軸にする場合は、DateTimeをそのままAddXY()に渡せます。
C#private void DrawDateTimeAxis()
{
chart1.Series.Clear();
chart1.ChartAreas.Clear();
var area = new ChartArea("MainArea");
area.AxisX.LabelStyle.Format = "HH:mm:ss";
area.AxisX.IntervalType = DateTimeIntervalType.Seconds;
area.AxisX.Title = "時刻";
area.AxisY.Title = "値";
chart1.ChartAreas.Add(area);
var series = new Series("センサー値")
{
ChartType = SeriesChartType.Line,
XValueType = ChartValueType.DateTime
};
series.Points.AddXY(DateTime.Now.AddSeconds(-3), 10);
series.Points.AddXY(DateTime.Now.AddSeconds(-2), 12);
series.Points.AddXY(DateTime.Now.AddSeconds(-1), 11);
series.Points.AddXY(DateTime.Now, 15);
chart1.Series.Add(series);
}
日付が数値のように表示される場合は、XValueType、LabelStyle.Format、IntervalTypeを確認してください。
5-5. データ更新時にグラフを再描画する方法
データ更新時の実装方法は、主に2つあります。
1つは、毎回Series.Points.Clear()してから全データを入れ直す方法です。データ件数が少ない場合は簡単で分かりやすいです。
C#series.Points.Clear();
foreach (var item in data)
{
series.Points.AddXY(item.Label, item.Value);
}
もう1つは、追加分だけAddXY()し、不要な古い点だけ削除する方法です。リアルタイム表示ではこちらの方が向いています。
C#series.Points.AddXY(DateTime.Now, newValue);
if (series.Points.Count > 100)
{
series.Points.RemoveAt(0);
}
大量データで毎回全消去・全追加を行うと重くなりやすいため、更新範囲を最小限にすることが重要です。
6. C# Chartでリアルタイムグラフを表示する方法
リアルタイムグラフは、センサー値、ログ、株価、CPU使用率、ネットワーク通信量など、時間とともに変化するデータを表示するために使います。
6-1. リアルタイム表示の基本的な考え方
リアルタイム表示の基本は、一定間隔でデータを取得し、ChartのSeriesに新しい点を追加することです。
流れは次のようになります。
Timerを開始する、一定間隔で値を取得する、Series.Points.AddXY()で新しい点を追加する、古い点を削除する、X軸の表示範囲を更新する、必要に応じて停止する。
WinFormsでは、System.Windows.Forms.Timerを使うとUIスレッド上でTickイベントが発生するため、簡単なリアルタイム表示に向いています。ただし、重い処理をTick内で実行すると画面が固まりやすくなります。
6-2. Timerを使って一定間隔でデータを追加する
以下は、Timerでランダムな値を追加する例です。
C#private readonly Timer timer = new Timer();
private readonly Random random = new Random();
private void Form1_Load(object sender, EventArgs e)
{
InitializeRealtimeChart();
timer.Interval = 500;
timer.Tick += Timer_Tick;
timer.Start();
}
private void InitializeRealtimeChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
var area = new ChartArea("MainArea");
area.AxisX.LabelStyle.Format = "HH:mm:ss";
area.AxisX.Title = "時刻";
area.AxisY.Title = "値";
chart1.ChartAreas.Add(area);
var series = new Series("リアルタイム値")
{
ChartType = SeriesChartType.Line,
XValueType = ChartValueType.DateTime,
BorderWidth = 2
};
chart1.Series.Add(series);
}
private void Timer_Tick(object? sender, EventArgs e)
{
double value = random.NextDouble() * 100;
DateTime now = DateTime.Now;
chart1.Series["リアルタイム値"].Points.AddXY(now, value);
}
これで500ミリ秒ごとに点が追加される折れ線グラフを作成できます。
6-3. 古いデータを削除して表示範囲を固定する
リアルタイムグラフでは、データを追加し続けると点数が増え続け、描画が重くなります。最新100件だけを表示する場合は、次のように古い点を削除します。
C#private const int MaxPoints = 100;
private void Timer_Tick(object? sender, EventArgs e)
{
var series = chart1.Series["リアルタイム値"];
double value = random.NextDouble() * 100;
DateTime now = DateTime.Now;
series.Points.AddXY(now, value);
while (series.Points.Count > MaxPoints)
{
series.Points.RemoveAt(0);
}
}
この方法なら、グラフ上の点数を一定に保てるため、長時間動かしても極端に重くなりにくくなります。
6-4. スクロールしながら最新データを表示する
最新データを右端に表示し続けたい場合は、X軸の最小値・最大値を更新します。ChartではDateTimeを内部的にOLE Automation日付として扱えるため、ToOADate()を使って範囲を指定できます。
C#private void Timer_Tick(object? sender, EventArgs e)
{
var series = chart1.Series["リアルタイム値"];
var area = chart1.ChartAreas["MainArea"];
DateTime now = DateTime.Now;
double value = random.NextDouble() * 100;
series.Points.AddXY(now, value);
while (series.Points.Count > MaxPoints)
{
series.Points.RemoveAt(0);
}
area.AxisX.Minimum = now.AddSeconds(-50).ToOADate();
area.AxisX.Maximum = now.ToOADate();
}
このようにすると、直近50秒程度の範囲だけを表示するリアルタイムチャートになります。
6-5. センサー値・ログ・株価・CPU使用率などの活用例
リアルタイムChartは、さまざまな用途で活用できます。
センサー値では、温度、湿度、圧力、電流、電圧、振動などを時系列で表示します。ログ監視では、エラー件数、リクエスト数、レスポンスタイムを可視化できます。株価や為替では、価格の推移を一定間隔で表示します。PC監視では、CPU使用率、メモリ使用量、ディスクI/O、ネットワーク使用量をグラフ化できます。
ただし、株価やセンサーなどの外部データを取得する処理は、Chartの描画処理とは分けて設計することが重要です。データ取得が遅い場合にUIスレッドを止めないよう、非同期処理やバックグラウンド処理を使います。
6-6. リアルタイム描画で重くなる原因と対策
リアルタイム描画が重くなる主な原因は、描画点数が多すぎる、更新間隔が短すぎる、毎回全データを再描画している、UIスレッドで重い処理をしている、ラベルやマーカーを大量に表示している、グリッドやアンチエイリアスなど見た目の処理が重い、というものです。
対策は次のとおりです。
表示点数を最新100〜1000件程度に制限する、更新間隔を100ミリ秒〜1000ミリ秒程度に調整する、データ取得と描画を分離する、画面に見える範囲だけ描画する、マーカーやラベルを減らす、必要に応じてScottPlotや商用ライブラリを使う。
標準Chartコントロールは学習用・小規模リアルタイム用途には便利ですが、数万点以上の高速更新を滑らかに描画する用途では専用ライブラリを検討するべきです。
7. Chartコントロールの見た目をカスタマイズする
グラフは、データを表示するだけでなく、見やすさも重要です。色、線の太さ、マーカー、軸ラベル、凡例、タイトル、ツールチップを調整すると、ユーザーに伝わりやすいグラフになります。
7-1. 線の色・太さ・マーカーを変更する
折れ線グラフの線を太くし、マーカーを付ける例です。
C#var series = chart1.Series["売上"];
series.Color = Color.DodgerBlue;
series.BorderWidth = 3;
series.MarkerStyle = MarkerStyle.Circle;
series.MarkerSize = 8;
series.MarkerColor = Color.White;
series.MarkerBorderColor = Color.DodgerBlue;
series.MarkerBorderWidth = 2;
複数系列を表示する場合は、系列ごとに色や線種を変えると比較しやすくなります。
C#chart1.Series["東京"].BorderDashStyle = ChartDashStyle.Solid;
chart1.Series["大阪"].BorderDashStyle = ChartDashStyle.Dash;
7-2. 軸ラベル・目盛り・グリッド線を調整する
軸ラベルやグリッド線を調整すると、グラフが読みやすくなります。
C#var area = chart1.ChartAreas["MainArea"];
area.AxisX.Title = "日付";
area.AxisY.Title = "売上";
area.AxisX.LabelStyle.Angle = -45;
area.AxisX.MajorGrid.Enabled = false;
area.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dot;
area.AxisY.MajorGrid.LineColor = Color.LightGray;
数値のフォーマットも指定できます。
C#area.AxisY.LabelStyle.Format = "#,0";
日付の場合は次のように指定します。
C#area.AxisX.LabelStyle.Format = "MM/dd";
7-3. 凡例・タイトル・背景色を設定する
タイトルと凡例は、グラフの意味を伝えるために重要です。
C#chart1.Titles.Clear();
chart1.Titles.Add(new Title("月別売上推移")
{
Font = new Font("Meiryo UI", 14, FontStyle.Bold)
});
chart1.Legends.Clear();
chart1.Legends.Add(new Legend("Legend")
{
Docking = Docking.Bottom,
Alignment = StringAlignment.Center
});
背景色を変更する例です。
C#chart1.BackColor = Color.White;
chart1.ChartAreas["MainArea"].BackColor = Color.WhiteSmoke;
業務アプリでは、派手な色よりも、背景を白または薄いグレーにして、データ系列を強調する方が見やすいことが多いです。
7-4. ツールチップやラベルで値を見やすくする
データ点にマウスを当てたときに値を表示したい場合は、ToolTipを設定します。
C#var series = chart1.Series["売上"];
series.ToolTip = "#VALX : #VALY";
値を常に表示したい場合は、ラベルを有効にします。
C#series.IsValueShownAsLabel = true;
series.LabelFormat = "#,0";
ただし、点数が多いグラフでラベルをすべて表示すると読みにくくなります。棒グラフや円グラフでは有効ですが、リアルタイム折れ線グラフではツールチップだけにするのがおすすめです。
7-5. 拡大・縮小・スクロールを有効にする
Chartコントロールでは、軸のScaleViewを使って拡大・スクロールを設定できます。
C#var area = chart1.ChartAreas["MainArea"];
area.AxisX.ScaleView.Zoomable = true;
area.AxisY.ScaleView.Zoomable = true;
area.CursorX.IsUserEnabled = true;
area.CursorX.IsUserSelectionEnabled = true;
area.CursorY.IsUserEnabled = true;
area.CursorY.IsUserSelectionEnabled = true;
area.AxisX.ScrollBar.Enabled = true;
area.AxisY.ScrollBar.Enabled = true;
データ量が多い場合は、最初から一部範囲だけを表示することもできます。
C#area.AxisX.ScaleView.Zoom(0, 100);
拡大・縮小を有効にすると、ユーザーが詳細を確認しやすくなりますが、操作説明やリセットボタンも用意すると親切です。
8. Chartコントロールでよくあるエラーと解決策
Chartコントロールを使うときによくあるトラブルをまとめます。
8-1. Chartコントロールがツールボックスに表示されない
Chartがツールボックスに表示されない場合は、まずプロジェクトの種類を確認してください。.NET FrameworkのWindows Formsアプリでは表示されることが多い一方、.NET 6や.NET 8のWinFormsでは標準のツールボックスに出ないことがあります。
対策として、.NET Frameworkプロジェクトで作成する、参照設定を確認する、NuGetで対応パッケージを追加する、外部ライブラリを使う、コードからChartを生成する、といった方法があります。
コードから生成する場合は次のようにします。
C#var chart = new Chart
{
Dock = DockStyle.Fill
};
chart.ChartAreas.Add(new ChartArea("MainArea"));
chart.Series.Add(new Series("Data")
{
ChartType = SeriesChartType.Line
});
this.Controls.Add(chart);
8-2. 名前空間や参照設定でエラーになる
次のようなエラーが出る場合があります。
The type or namespace name 'DataVisualization' does not exist
この場合は、参照設定またはパッケージが不足している可能性があります。
.NET Frameworkでは、System.Windows.Forms.DataVisualizationへの参照を追加します。コードでは次を追加します。
C#using System.Windows.Forms.DataVisualization.Charting;
.NET 6以降では、ターゲットフレームワークとChart関連パッケージの対応状況を確認してください。無理に標準Chartを使うより、ScottPlotやLiveCharts2へ切り替えた方が早い場合もあります。
8-3. グラフが表示されない・点が描画されない
グラフが表示されない場合は、次の点を確認します。
ChartAreaが追加されているか、Seriesが追加されているか、Series.ChartAreaが存在するChartArea名と一致しているか、Points.AddXY()でデータを追加しているか、Y値がすべて同じで軸範囲が分かりにくくなっていないか、フォーム上でChartのサイズが0になっていないか、Visibleがfalseになっていないか。
特に多いのは、Seriesだけ作ってChartに追加していないケースです。
C#var series = new Series("Data");
series.Points.AddXY(1, 10);
// これを忘れると表示されない
chart1.Series.Add(series);
8-4. X軸の日付や数値が正しく表示されない
DateTimeをX軸にしたとき、意図しない数値が表示されることがあります。その場合は、XValueTypeとLabelStyle.Formatを設定します。
C#series.XValueType = ChartValueType.DateTime;
area.AxisX.LabelStyle.Format = "yyyy/MM/dd HH:mm:ss";
また、X軸をカテゴリとして扱いたい場合と、数値・日付の連続軸として扱いたい場合では、データの渡し方が変わります。カテゴリ名を表示したいなら文字列、時間軸としてスクロールしたいならDateTimeを使うと整理しやすいです。
8-5. リアルタイム更新で画面が固まる
リアルタイム更新で画面が固まる場合は、Tickイベント内で重い処理をしている可能性があります。
避けるべき処理は、データベースアクセス、ファイル全体の読み込み、ネットワーク通信、大量データの全再描画、複雑な集計処理です。
対策として、データ取得をバックグラウンドで行う、UI更新だけをUIスレッドで行う、描画点数を制限する、更新間隔を長くする、Chart更新処理を軽くする、必要なら専用ライブラリを使う、という方法があります。
バックグラウンドスレッドからChartを更新する場合は、InvokeまたはBeginInvokeを使います。
C#private void AddPointFromBackground(DateTime time, double value)
{
if (chart1.InvokeRequired)
{
chart1.BeginInvoke(new Action(() => AddPointFromBackground(time, value)));
return;
}
chart1.Series["Data"].Points.AddXY(time, value);
}
8-6. .NET Core・.NET 5以降で使うときの注意点
.NET Core、.NET 5、.NET 6、.NET 8以降でChartコントロールを使う場合は、.NET Framework時代のサンプルコードがそのまま動かないことがあります。dotnet/winforms-datavisualizationリポジトリでは、WinForms向けCharting機能を.NET Core 3向けに有効化するために移植・オープンソース化した旨が説明されています。
ただし、新規開発では、ターゲット環境に合わせてライブラリを選ぶ方が安全です。
.NET Frameworkの既存WinFormsならChartコントロール、.NET 6以降のWinFormsならScottPlotまたは対応パッケージ、WPFならLiveCharts2やOxyPlot、WebやBlazorならPlotly系、産業用途や大量データなら商用ライブラリ、という考え方がおすすめです。
9. C#向けChartライブラリ比較
C# Chartsを本格的に使うなら、標準Chartコントロールだけでなく、外部ライブラリも比較しておくと失敗しにくくなります。
9-1. 標準Chartコントロールと外部ライブラリの比較ポイント
比較するときは、以下の観点を見ると選びやすくなります。
対応UIがWinFormsかWPFかBlazorか、無料か商用か、ライセンスは何か、リアルタイム描画に強いか、大量データに強いか、見た目がモダンか、ズームやパンが使いやすいか、MVVMに合うか、ドキュメントやサンプルが豊富か、NuGetで導入しやすいか、メンテナンスが継続しているか。
小規模な社内ツールなら標準Chartでも十分ですが、アプリの品質や将来の拡張性を重視するなら、最初から外部ライブラリを選ぶ価値があります。
9-2. LiveCharts・LiveCharts2の特徴
LiveCharts2は、WPFやWinForms、Blazor、MAUIなど複数環境で使える.NET向けチャートライブラリです。公式サイトでは、複数のデバイスやフレームワークで動作し、MITライセンスの無料版と有料版があることが説明されています。
LiveCharts2の強みは、見た目がモダンで、アニメーションやデータバインディングとの相性がよいことです。WPFでMVVM構成のアプリを作る場合、ViewModel側のコレクション更新に合わせてグラフを更新しやすい点が魅力です。
一方で、極端な大量データや超高速リアルタイム描画では、用途に応じて性能検証が必要です。見た目や開発体験を重視するWPFアプリに向いています。
9-3. ScottPlotの特徴
ScottPlotは、.NET向けの無料オープンソース描画ライブラリです。公式サイトでは、折れ線グラフ、棒グラフ、円グラフ、散布図などを数行のコードで作成でき、大量データをインタラクティブに表示しやすいライブラリとして紹介されています。
WinFormsで使う場合は、ScottPlot.WinFormsをNuGetで追加し、FormsPlotをフォームに配置して使います。
ScottPlotは、シンプルなAPI、軽快な描画、豊富なサンプルが魅力です。WinFormsで標準Chartよりきれいで実用的なグラフを作りたい場合、非常に有力な選択肢です。
9-4. OxyPlotの特徴
OxyPlotは、.NET向けのクロスプラットフォームなプロットライブラリです。公式サイトでは、MITライセンスのクロスプラットフォームプロットライブラリとして紹介されています。
OxyPlotは、WPF、WinForms、Xamarinなど複数環境で使えることが特徴です。PlotModelを作成し、UI側のPlotViewにバインドする設計のため、WPFアプリでも扱いやすいです。
派手なアニメーションよりも、堅実なグラフ描画やクロスプラットフォーム性を重視する場合に向いています。
9-5. Plotly.NET・Plotly.Blazorの特徴
Plotly.NETは、plotly.jsのチャートを.NETから生成するためのライブラリです。公式ドキュメントでは、.NETプログラミング言語でplotly.jsチャートを生成・レンダリングする機能を提供すると説明されています。
Plotly系の強みは、ブラウザ上でのインタラクティブ表示です。ズーム、パン、ホバー、凡例クリック、レスポンシブ表示などを使いやすく、Webダッシュボードに向いています。
C#だけで完結するWinFormsアプリというより、ASP.NET Core、Blazor、レポート出力、ノートブック、Web可視化で力を発揮します。
9-6. LightningChart・TeeChart・DevExpressなど商用ライブラリの特徴
商用ライブラリは、無料ライブラリより導入コストがかかりますが、その分サポート、パフォーマンス、豊富な部品、業務利用での安心感があります。
LightningChartは高性能リアルタイム描画を前面に出している商用チャートライブラリで、公式サイトでもリアルタイムかつ要求の厳しいデータ可視化アプリ向けの高性能チャートフレームワークとして紹介されています。
TeeChartやDevExpressは、業務アプリ向けUI部品の一部としてチャート機能を提供しており、帳票、ダッシュボード、グリッド、入力部品などと統合しやすいのが特徴です。
工場監視、医療機器、金融取引、計測装置、研究開発ツールなど、描画性能やサポートが重要な分野では商用ライブラリの検討価値が高くなります。
9-7. 無料・商用・高性能・リアルタイム用途別の選び方
無料で始めたいなら、WinFormsでは標準ChartまたはScottPlot、WPFではLiveCharts2またはOxyPlot、WebではPlotly.NETやJavaScript系チャートが候補になります。
見た目を重視するならLiveCharts2、手軽さと性能のバランスならScottPlot、堅実なクロスプラットフォーム性ならOxyPlot、Webのインタラクティブ表示ならPlotly系、大量データや高速リアルタイムならLightningChartなどの商用ライブラリを検討するとよいです。
重要なのは、最初に「何を表示したいか」ではなく「どのくらいのデータを、どの頻度で、どの環境に表示するか」を決めることです。
10. 用途別に見るC# Chartsのおすすめ構成
ここでは、用途別におすすめのC# Charts構成を整理します。
10-1. 学習用・小規模ツールなら標準Chartコントロール
C#でグラフ描画を学びたい場合や、.NET FrameworkのWinFormsで小規模な社内ツールを作る場合は、標準Chartコントロールで十分です。
メリットは、導入が簡単で、ChartArea、Series、Points.AddXY()の基本を覚えればすぐに使えることです。折れ線グラフ、棒グラフ、円グラフ、散布図など基本的なグラフは一通り作れます。
ただし、見た目のモダンさや大量データの処理性能では外部ライブラリに劣ることがあります。
10-2. WinFormsで手軽に高品質なグラフを作るならScottPlot
WinFormsで新しくアプリを作るなら、ScottPlotは有力な候補です。NuGetで導入しやすく、サンプルも豊富で、標準Chartよりも少ないコードで見やすいグラフを作れる場面があります。
特に、CSVビューア、ログ解析ツール、測定値表示、簡易ダッシュボードなどに向いています。
標準Chartで実装していて、表示速度や操作性に不満が出てきたら、ScottPlotへの移行を検討するとよいでしょう。
10-3. WPFでMVVMやアニメーションを使うならLiveCharts2
WPFでMVVMパターンを使う場合は、LiveCharts2が扱いやすいです。ObservableCollectionやプロパティ変更通知と組み合わせることで、ViewModelの値を更新するだけでチャートを更新しやすくなります。
また、見た目がモダンでアニメーションも使いやすいため、ユーザー向けアプリやダッシュボードに向いています。
10-4. 大量データや高速リアルタイム描画なら商用ライブラリ
大量データや高速リアルタイム描画が必要な場合は、標準Chartコントロールだけで対応しようとせず、専用ライブラリを検討してください。
たとえば、1秒間に何十回も更新する、数十万点以上を表示する、複数チャンネルのセンサー値を同時に表示する、長時間連続稼働する、といった要件では、描画エンジンの性能が重要になります。
このような用途では、LightningChart、SciChart、DevExpress、TeeChartなどの商用ライブラリが候補になります。
10-5. WebアプリやBlazorならJavaScript連携やPlotly系を検討する
ASP.NET CoreやBlazorでチャートを表示する場合は、ブラウザ上で動くチャートを使うのが自然です。
Plotly系、Chart.js、EChartsなどをBlazorから利用すると、ズーム、ホバー、凡例操作、レスポンシブ対応などを実現しやすくなります。
サーバー側で画像としてグラフを生成する方法もありますが、ユーザーが操作するダッシュボードなら、Web系チャートの方が使いやすいことが多いです。
11. 実践サンプル:C#でリアルタイム折れ線グラフを作る
ここでは、WinFormsのChartコントロールを使って、ランダムな値をリアルタイムに表示する折れ線グラフを作ります。
11-1. サンプルアプリの仕様
仕様は次のとおりです。
500ミリ秒ごとにランダムな値を生成する、X軸に現在時刻を表示する、Y軸に0〜100の値を表示する、最新100件だけを表示する、開始ボタンで更新を開始する、停止ボタンで更新を停止する。
フォームには、chart1、buttonStart、buttonStopを配置します。
11-2. Chartコントロールの配置と初期設定
まず、Chartを初期化します。
C#using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
public partial class Form1 : Form
{
private readonly Timer timer = new Timer();
private readonly Random random = new Random();
private const int MaxPoints = 100;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeChart();
timer.Interval = 500;
timer.Tick += Timer_Tick;
}
private void InitializeChart()
{
chart1.ChartAreas.Clear();
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.Titles.Clear();
var area = new ChartArea("MainArea");
area.AxisX.Title = "時刻";
area.AxisY.Title = "値";
area.AxisX.LabelStyle.Format = "HH:mm:ss";
area.AxisY.Minimum = 0;
area.AxisY.Maximum = 100;
area.AxisX.MajorGrid.Enabled = false;
chart1.ChartAreas.Add(area);
var series = new Series("リアルタイム値")
{
ChartType = SeriesChartType.Line,
ChartArea = "MainArea",
XValueType = ChartValueType.DateTime,
BorderWidth = 2
};
chart1.Series.Add(series);
chart1.Titles.Add("リアルタイム折れ線グラフ");
}
}
11-3. Timerでランダムデータを追加する
TimerのTickイベントで値を追加します。
C#private void Timer_Tick(object? sender, EventArgs e)
{
DateTime now = DateTime.Now;
double value = random.NextDouble() * 100;
var series = chart1.Series["リアルタイム値"];
series.Points.AddXY(now, value);
}
これで、Timerが動いている間はグラフに点が追加されます。
11-4. 最新100件だけを表示する
データが増え続けないように、最新100件だけを残します。
C#private void Timer_Tick(object? sender, EventArgs e)
{
DateTime now = DateTime.Now;
double value = random.NextDouble() * 100;
var series = chart1.Series["リアルタイム値"];
series.Points.AddXY(now, value);
while (series.Points.Count > MaxPoints)
{
series.Points.RemoveAt(0);
}
var area = chart1.ChartAreas["MainArea"];
if (series.Points.Count > 1)
{
area.AxisX.Minimum = series.Points[0].XValue;
area.AxisX.Maximum = series.Points[series.Points.Count - 1].XValue;
}
}
これで、古い点が削除され、表示範囲が最新データに追従します。
11-5. 開始・停止ボタンを実装する
開始ボタンと停止ボタンのイベントを追加します。
C#private void buttonStart_Click(object sender, EventArgs e)
{
timer.Start();
}
private void buttonStop_Click(object sender, EventArgs e)
{
timer.Stop();
}
必要に応じて、開始中は開始ボタンを無効化し、停止ボタンだけ押せるようにします。
C#private void buttonStart_Click(object sender, EventArgs e)
{
timer.Start();
buttonStart.Enabled = false;
buttonStop.Enabled = true;
}
private void buttonStop_Click(object sender, EventArgs e)
{
timer.Stop();
buttonStart.Enabled = true;
buttonStop.Enabled = false;
}
11-6. 実運用向けに改善すべきポイント
実運用では、ランダム値ではなくセンサー、API、データベース、ログファイルなどから値を取得します。その場合は、データ取得処理とChart更新処理を分けることが重要です。
改善ポイントは、データ取得を非同期化する、UIスレッドで重い処理をしない、例外処理を追加する、取得失敗時の表示を用意する、表示件数と保存件数を分ける、ログ保存機能を追加する、軸範囲を自動調整または手動設定できるようにする、開始・停止・クリアボタンを用意する、描画間隔を設定画面で変更できるようにする、などです。
12. C# Chartsのパフォーマンス最適化
C# Chartsで重要なのは、表示したいデータをすべて描画しようとしないことです。人間が画面上で判別できる点数には限界があるため、必要な粒度に加工してから描画する方が実用的です。
12-1. 描画点数を減らす・間引く
大量データを扱う場合は、すべての点を描画するのではなく、間引きます。
C#for (int i = 0; i < data.Count; i += 10)
{
series.Points.AddXY(data[i].Time, data[i].Value);
}
画面幅が1000ピクセル程度なら、数十万点をそのまま描画しても視覚的な差が分からないことがあります。最小値・最大値・平均値などに集約して表示する方法も有効です。
12-2. 更新頻度を調整する
データ取得頻度と描画頻度は分けて考えます。
たとえば、センサー値を10ミリ秒ごとに取得していても、画面更新は200ミリ秒ごとで十分なことがあります。すべての取得データを保存し、表示だけ間引く設計にすると、性能と精度を両立できます。
C#timer.Interval = 200;
リアルタイム表示では、更新頻度を上げすぎるよりも、安定して滑らかに表示できる間隔を選ぶことが重要です。
12-3. UIスレッドをブロックしない
WinFormsやWPFのUIは、UIスレッドで動きます。UIスレッドで重い処理をすると、画面が固まります。
避けるべきコードは次のようなものです。
C#private void Timer_Tick(object sender, EventArgs e)
{
// 重いDB処理
// 大きなCSV読み込み
// 複雑な集計
// 大量点の全再描画
}
データ取得や集計はバックグラウンドで行い、Chartへの反映だけをUIスレッドで行いましょう。
12-4. 非同期処理とInvokeの使い方
バックグラウンドタスクでデータを取得し、UI更新だけBeginInvokeで行う例です。
C#private async void buttonStart_Click(object sender, EventArgs e)
{
await Task.Run(async () =>
{
while (true)
{
double value = GetSensorValue();
DateTime time = DateTime.Now;
BeginInvoke(new Action(() =>
{
AddChartPoint(time, value);
}));
await Task.Delay(500);
}
});
}
private void AddChartPoint(DateTime time, double value)
{
var series = chart1.Series["リアルタイム値"];
series.Points.AddXY(time, value);
while (series.Points.Count > 100)
{
series.Points.RemoveAt(0);
}
}
実際には、停止用のCancellationTokenを使って安全にループを終了できるようにします。
12-5. 大量データでは専用ライブラリを検討する
標準Chartコントロールでパフォーマンス対策をしても限界があります。
大量データを扱う場合は、ScottPlot、LiveCharts2、OxyPlot、LightningChart、SciChartなどを検討してください。特にリアルタイム計測、工場監視、医療・研究用途、金融チャートなどでは、描画性能や安定性がアプリ全体の品質に直結します。
無料ライブラリで足りるか、商用ライブラリが必要かは、必ず実データに近い条件で検証することが大切です。
13. C# Chartsに関するよくある質問
13-1. C#で無料で使えるChartライブラリはどれか
無料で使える代表的なC# Chartライブラリには、標準Chartコントロール、ScottPlot、LiveCharts2、OxyPlot、Plotly.NETなどがあります。
WinFormsで手軽に使うなら標準ChartまたはScottPlot、WPFならLiveCharts2またはOxyPlot、WebやBlazorならPlotly.NETやJavaScript系チャートが候補です。
ライセンスはプロジェクトごとに確認してください。たとえばOxyPlotはMITライセンスのクロスプラットフォーム.NETプロットライブラリとして紹介されています。
13-2. Chartコントロールは.NET 6や.NET 8で使えるのか
従来のChartコントロールは、主に.NET FrameworkのWinFormsで使われてきました。.NET 6や.NET 8では、プロジェクト作成直後に同じ感覚で使えるとは限りません。
.NET 6以降で標準Chart相当を使いたい場合は、対応するNuGetパッケージや移植版を確認する必要があります。NuGetのWinForms.DataVisualizationは、.NET FrameworkのSystem.Windows.Forms.DataVisualizationを継続するWinForms向けコントロールとして.NET 6+対応を説明しています。
新規開発では、ScottPlotなど.NET 6以降で使いやすいライブラリを選ぶ方がスムーズな場合もあります。
13-3. WPFでもChartコントロールは使えるのか
WPFでWinFormsのChartコントロールを使うには、WindowsFormsHostを使って埋め込む方法があります。ただし、WPFらしいデータバインディングやMVVMとの相性を考えると、LiveCharts2やOxyPlotなどWPF向けに使いやすいライブラリを選ぶ方が自然です。
既存のWinForms Chart資産を流用したい場合は埋め込みも選択肢ですが、新規のWPFアプリならWPF対応ライブラリをおすすめします。
13-4. リアルタイムチャートは何ミリ秒間隔まで対応できるのか
何ミリ秒まで対応できるかは、ライブラリ、PC性能、点数、系列数、描画内容、マーカーやラベルの有無、データ取得処理の重さによって変わります。
標準Chartコントロールであれば、まずは200〜1000ミリ秒程度の更新間隔から試すのが現実的です。100ミリ秒以下で大量データを描画したい場合は、表示点数を制限し、実機で検証してください。
数万点以上を高頻度で更新する用途では、ScottPlotや商用ライブラリを検討するのが安全です。
13-5. ExcelのようなグラフをC#で作れるのか
C#でもExcelのような折れ線グラフ、棒グラフ、円グラフ、散布図は作れます。標準Chartコントロールでも基本的な見た目は再現できます。
ただし、Excelのような操作性、きれいなテーマ、豊富なグラフ種類、インタラクティブな編集機能まで求める場合は、外部ライブラリや商用コンポーネントを使う方が効率的です。
また、Excelファイルそのものにグラフを出力したい場合は、ClosedXML、EPPlus、NPOI、Microsoft Office Interopなど、Excel操作用ライブラリを検討します。
まとめ
C# Chartsでグラフを描画する方法は、WinFormsのChartコントロールから外部ライブラリ、Web系チャート、商用ライブラリまで幅広くあります。
まずC#でグラフを学びたい場合や、.NET FrameworkのWinFormsで小規模ツールを作る場合は、Chartコントロールが分かりやすい選択肢です。ChartArea、Series、Points.AddXY()の基本を覚えれば、折れ線グラフ、棒グラフ、円グラフ、散布図、複数系列グラフ、リアルタイムグラフを作成できます。
一方で、新規開発や大量データ、高速リアルタイム描画、WPFのMVVM、Webダッシュボードを考えるなら、ScottPlot、LiveCharts2、OxyPlot、Plotly.NET、LightningChartなども比較して選ぶべきです。
C# Chartsで失敗しないポイントは、最初に用途を明確にすることです。学習用か、業務アプリか、リアルタイム監視か、Webダッシュボードか、大量データ分析かによって、最適な選択肢は変わります。
小さく始めるならChartコントロール、本格的に作るなら用途に合ったライブラリ。これがC#でグラフ描画を実装するときの基本方針です。

