【WPF】C#+ScottPlotで折れ線グラフのユーザーコントロールを作る!

当ページのリンクには広告が含まれています。

今回はScottPlotを使って、WPFで使える折れ線グラフ描画用のユーザーコントロールを作ってみました。

画面に張り付けて、データをセットするだけで簡単に折れ線グラフが表示できます。

X軸は数字、日付、日時にすることも可能になっています。

目次

折れ線グラフの表示例

このユーザーコントロールを使うと、次のような折れ線グラフが表示できます。

X軸データに日付又は時刻の数値(詳細は後述)を指定し、IsDateTimeTicksプロパティを true にすることで、X軸を日付や日時にすることが出来ます。また、DataTimeFormatterプロパティにより、日付フォーマットを指定することも可能です。

ユーザーコントロールの使い方

では、ユーザーコントロールの使い方について解説していきます。

メソッド

メソッドは次の2つが用意されています。

複数の折れ線グラフを表示するため、Y軸のデータをListで保持しています。

Clearメソッドは、グラフの消去と共に、Y軸の Listもクリアしています。

メソッド名引数の説明内容
void Clear()グラフ及びY軸データの消去
void Draw(string title)title:グラフのタイトルグラフの描画

プロパティ一覧

次のプロパティが用意されています。

プロパティ名初期値内容
double[] XValuesnullX軸のデータ
List<double[]> YValuesnullY軸のデータ
string[] Legendsnull凡例に表示するタイトル(Y軸の数だけ用意すること)
bool ShowLegendtruetrue にすると凡例が表示される
string[] Colorsnull線の色(Y軸の数だけ用意すること)
bool IsDateTimeTicksfalsetrue にするとX軸の値を日付型として扱う
string DataTimeFormatternullX軸の日付フォーマットを指定する。
例:"yyyy年MM月dd日 HH時mm分ss秒"
int XTickRotation0X軸の目盛りを表示する角度
string XAxisTitlenullX軸のタイトル
string YAxisTitlenullY軸のタイトル
int[] YAxisNonullY軸データに対して、1軸と2軸のどちらに描画するかを指定。
0→1軸目、1→2軸目
例:Y軸データが4つある場合、 new int{1,0,0,1}

使い方とサンプルソース

使い方のサンプルは次の様になります。

XValuesとYValues に値を設定し、 Draw プロパティを呼び出せば折れ線グラフが表示されます。

Drawプロパティにはグラフのタイトルを指定してください。

注意点としては、YValues に折れ線の値を Add メソッドで追加していく仕様なので、最初にClear メソッドを呼んで Listの中身をクリアしておく点です。

例えば、ボタンをクリックする度に新しい値で折れ線グラフを表示するような場合、Clearメソッドを呼ばないと、前回にAddしたYValuse の内容までグラフ表示されてしまうことになります。

X軸が数値の折れ線グラフ

次のサンプルは4つの折れ線グラフを描画するサンプルですが、上記の注意点を踏まえて最初にClear メソッドを呼んでいます。

uxLineChart.Clear();

//uxLineBarChart.Colors = new string[] { "orange","red","gray","pink","magenta"};
uxLineChart.XValues = new double[] { 1.5, 2.0, 2.5, 3.0, 3.5 };
uxLineChart.YValues.Add(new double[] { 100, 100, 200, 50, 50 });
uxLineChart.YValues.Add(new double[] { 110, 150, 120, 150, 130 });
uxLineChart.YValues.Add(new double[] { 120, 140, 160, 120, 140 });
uxLineChart.YValues.Add(new double[] { 200, 100, 160, 220, 180 });
uxLineChart.XAxisTitle = "X軸";
uxLineChart.YAxisTitle = "Y軸";
uxLineChart.YAxisNo = new int[] { 1, 0, 0, 1 };

uxLineChart.Draw("折れ線グラフ");

X軸が日付の折れ線グラフ

X軸に日時を表示したい場合、DateTime型の値を ToOADate メソッドで実数に変換した結果を XValues にセットすると共に、IsDateTimeTicks プロパティに trueをセットして下さい。

与えるデータに時刻が含まれるか含まれないかで、X軸に日付だけ表示されるか、時刻まで表示されるか変わります。

尚、X軸に表示するDateTimeのデータは必ず連続している必要はなく、飛び飛びでも構いません。

飛び飛びの場合は、X軸のスケールが適切に調整されます。

uxLineChart.Clear();

//X軸に日付を設定する
uxLineChart.XValues = new double[] {
    DateTime.Parse("2021/02/10").ToOADate(),
    DateTime.Parse("2021/02/12").ToOADate(),
    DateTime.Parse("2021/02/15").ToOADate(), 
    DateTime.Parse("2021/03/01").ToOADate(), 
    DateTime.Parse("2021/03/02").ToOADate()
};

uxLineChart.YValues.Add(new double[] { 100, 100, 200, 50, 50 });
uxLineChart.YValues.Add(new double[] { 110, 150, 120, 150, 130 });
uxLineChart.YValues.Add(new double[] { 120, 140, 160, 120, 140 });
uxLineChart.YValues.Add(new double[] { 200, 100, 160, 220, 180 });
uxLineChart.XAxisTitle = "X軸";
uxLineChart.YAxisTitle = "Y軸";
uxLineChart.YAxisNo = new int[] { 1, 0, 0, 1 };
uxLineChart.IsDateTimeTicks = true;

uxLineChart.Draw("折れ線グラフ");

X軸が日時の折れ線グラフ

X軸に日時を表示したい場合、日時を持つDateTime型に対して ToOADate() で実数に変換した結果をセットすると共に、IsDateTimeTicks プロパティに true をセットして下さい。

次のサンプルでは、現在時刻に対して、3秒、6秒、10秒、11秒を加算した値をX軸に表示しています。

uxLineChart.Clear();

//X軸を日時(日付と時刻)に設定
uxLineChart.XValues = new double[] {
    DateTime.Now.ToOADate(),
    DateTime.Now.AddSeconds(3).ToOADate(), 
    DateTime.Now.AddSeconds(6).ToOADate(), 
    DateTime.Now.AddSeconds(10).ToOADate(), 
    DateTime.Now.AddSeconds(11).ToOADate()
};
uxLineChart.YValues.Add(new double[] { 100, 100, 200, 50, 50 });
uxLineChart.YValues.Add(new double[] { 110, 150, 120, 150, 130 });
uxLineChart.YValues.Add(new double[] { 120, 140, 160, 120, 140 });
uxLineChart.YValues.Add(new double[] { 200, 100, 160, 220, 180 });
uxLineChart.XAxisTitle = "X軸";
uxLineChart.YAxisTitle = "Y軸";
uxLineChart.YAxisNo = new int[] { 1, 0, 0, 1 };
uxLineChart.IsDateTimeTicks = true;

uxLineChart.Draw("折れ線グラフ");

X軸のフォーマットを指定した折れ線グラフ

X軸のフォーマットを指定したい場合は、IsDateTimeTicks プロパティに true をセットすると共に、DateTimeFormatter プロパティにフォーマットを指定します。

この例では "HH時mm分" という表記で、時間と秒だけを指定しています。

uxLineChart.Clear();

//X軸を日時(日付と時刻)に設定
uxLineChart.XValues = new double[] {
    DateTime.Now.ToOADate(),
    DateTime.Now.AddSeconds(3).ToOADate(), 
    DateTime.Now.AddSeconds(6).ToOADate(), 
    DateTime.Now.AddSeconds(10).ToOADate(), 
    DateTime.Now.AddSeconds(11).ToOADate()
};
uxLineChart.YValues.Add(new double[] { 100, 100, 200, 50, 50 });
uxLineChart.YValues.Add(new double[] { 110, 150, 120, 150, 130 });
uxLineChart.YValues.Add(new double[] { 120, 140, 160, 120, 140 });
uxLineChart.YValues.Add(new double[] { 200, 100, 160, 220, 180 });
uxLineChart.XAxisTitle = "X軸";
uxLineChart.YAxisTitle = "Y軸";
uxLineChart.YAxisNo = new int[] { 1, 0, 0, 1 };
uxLineChart.IsDateTimeTicks = true;
uxLineChart.DateTimeFormatter = "HH時mm分";

uxLineChart.Draw("折れ線グラフ");

ユーザーコントロールの解説

事前準備

今回はフリーのチャートライブラリである ScottPlot を使っていますので、あらかじめNuGetによるインストールが必要です。

NuGetから 「scott」で検索し ScottPlot.WPFを選んでインストールして下さい。下記画面ではバージョン4.1.29 ですが、2023年11月現在においては 4.1.68 がリリースされています。Ver5.0も存在しますが、まだβ版なので安定を望むのであればバージョン4.xx.xx がお勧めです。

ScottPlotのインストールについて詳しい情報を知りたい方は、 こちら の記事をご覧ください。

また、ユーザーコントロールの作り方が知りたい方は、こちらの記事をご覧ください。

レイアウトの作成

今回は、プロジェクト名を WpfLinteChartTest ユーザーコントロール名を ScottLineChartControl で作成しています。

必要に応じて、適宜名前は変更して下さい。

まず、レイアウトエディタでツールボックスに表示されている WpfPlot を張り付けておいて下さい。

XAMLのソースコード

以下がXAMLのソースコードです。

ScottPlotチャートコントロールに対して、uxScottPlot という名前を付けています。

<UserControl x:Class="WpfPiChartTest.ScottLineChartControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfPiChartTest"
             mc:Ignorable="d" 
             d:DesignHeight="400" d:DesignWidth="400">
    <Grid>
        <WpfPlot x:Name="uxScottPlot"/>

    </Grid>
</UserControl>

C#のソースコード

以下がC#側のソースコードになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ScottPlot;

namespace WpfPiChartTest
{
    /// <summary>
    /// ScottLineChartControl.xaml の相互作用ロジック
    /// </summary>
    public partial class ScottLineChartControl : UserControl
    {
        public double[] XValues { get; set; }                               //X軸のデータ
        public List<double[]> YValues { get; set; } = new List<double[]>(); //Y軸のデータ
        public string[] Legends { get; set; }                               //凡例に表示するのラベル
        public bool ShowLegend { get; set; } = true;                        //凡例を表示
        public string[] Colors { get; set; }                                //線の色
        public bool IsDateTimeTicks { get; set; } = false;                  //X軸をDateTime型として扱う
        public string DateTimeFormatter { get; set; }                        //X軸をDateTime型として扱う場合のフォーマット
        public int XTickRotation { get; set; } = 0;                         //X軸ラベルの角度
        public string XAxisTitle { get; set; }                              //X軸のタイトル
        public string YAxisTitle { get; set; }                              //Y軸のタイトル
        public int[] YAxisNo { get; set; }                                  //Y軸の指定
        //コンストラクタ
        public ScottLineChartControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param n
        public void Draw(string title)
        {
            //描画エリアのクリア
            uxScottPlot.Plot.Clear();
            //グラフタイトルの表示
            uxScottPlot.Plot.Title(title);
            //折れ線の色が指定されていた場合、配列に格納
            var colors = (Colors == null) ? null : Colors.Select(i => System.Drawing.Color.FromName(i)).ToArray();

            //描画データを取り出してグラフを作成
            for (int no = 0; no < YValues.Count; no++)
            {
                //折れ線の色を取得
                System.Drawing.Color? color = null;
                if (Colors != null) color = colors[no];

                //折れ線グラフの作成
                var scat = uxScottPlot.Plot.AddScatter(
                            XValues,                                        //X軸のデータ
                            YValues[no],                                    //Y軸のデータ
                            lineWidth: 2,                                   //線の幅
                            markerSize: 0,                                  //点(マーカー)のサイズ
                            lineStyle: LineStyle.Solid,                     //線の種類
                            color: color,                                   //線の色
                            label: (Legends == null) ? null : Legends[no]); //凡例

                //Y軸の指定があれば、軸番号をセット
                if (YAxisNo != null)  scat.YAxisIndex = YAxisNo[no];
            }

            //X軸の扱い方(数値 or DateTime型)とラベルの角度を設定
            uxScottPlot.Plot.XAxis.DateTimeFormat(IsDateTimeTicks);
            if (IsDateTimeTicks && DateTimeFormatter != null)
            {
                uxScottPlot.Plot.XAxis.TickLabelFormat(DateTimeFormatter, dateTimeFormat: true);
            }
            uxScottPlot.Plot.XAxis.TickLabelStyle(rotation:XTickRotation);

            //グリッド線の表示
            uxScottPlot.Plot.Grid(true,lineStyle:LineStyle.Solid);
            //フレーム(外枠)の表示
            uxScottPlot.Plot.Frameless(false);
            //凡例の表示
            if (ShowLegend) uxScottPlot.Plot.Legend(true);
            //X軸のタイトルを設定
            uxScottPlot.Plot.XLabel(XAxisTitle);
            //Y軸のタイトルを設定
            uxScottPlot.Plot.YLabel(YAxisTitle);
            //軸の指定があれば、Y2軸番号を表示
            uxScottPlot.Plot.YAxis2.Ticks(YAxisNo != null ? true : false);

            //グラフを描画
            uxScottPlot.Render();
        }

        /// <summary>
        /// グラフ表示エリアとデータのクリア
        /// </summary>
        public void Clear()
        {
            uxScottPlot.Plot.Clear();
            YValues.Clear();
        }
    }
}

グラフ描画のポイント

ScottPlotで折れ線を引く場合、 AddScatterメソッドを使用します。

AddScatterの引数には、X軸、Y軸のデータや、折れ線の色と太さ、線の種類、凡例に表示するラベル、マーカーの形やサイズなどが指定できます。

今回はマーカーサイズを0にし、線の種類は LineStyle.Solid を固定で指定していますので、必要なら別途プロパティを設置し、外部から変更できるようにしても良いと思います。

凡例については、ShowLegend プロパティで外部から表示/非表示を設定できるようにしていますが、そもそも Legends プロパティに何も設定しなければ、凡例の枠さえ表示されないようです。

線の色指定についても、前回の記事「【WPF】ScottPlotで円グラフのユーザーコントロールを作ってみました」と同じ理由(Color.Red などの指定だと、stem.Drawing.Color と System.Window.Media.Color が被るので、いちいち stem.Drawing.Color.Red と記述しないといけなくなる)から、文字列で指定するようになっています。

まとめ

フリーのチャートライブラリ ScottPlot を使って、WPFで使える円グラフのユーザーコントロールについて、使い方とソースコードを紹介しました。

毎回円グラフを書くのに、いちいちScottPlotのコードを記述するのは面倒です。

ユーザーコントロールにしておけば、張り付けるだけで簡単にグラフが書けますので、是非ご活用ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次