メインコンテンツまでスキップ

WPFで棒グラフを表示する

土井
開発一部第2課

プロジェクトでWPF内での棒グラフの実装を行うことになり、苦労したことですし、せっかくなので調査した内容等をこちらで紹介します。
WPFで棒グラフを表示するためには様々な方法がありますが、
その中の一つとして、WPF内でWindows Form用のコントロールを使う方法があります。
今回MVVMモデルで記載しております。

動作環境:.NetFramework4.7.2 + xaml

ソリューションエクスプローラーのプロジェクトを右クリックし、「追加」→「参照」をクリックしてください。その後表示される「参照マネージャー」内の「アセンブリ」から以下の項目の参照を追加してください。

  • WindowsFormIntegration
  • System.Windows.Forms
  • System.Windows.Forms.DataVisualization

画像1

※上記の方法でWindowsFormIntegrationの参照ができなかった場合
「参照マネージャー」を開き、参照ボタンを押下します。
その後、以下のフォルダ内にある「WindowsFormsIntegration.dll」を選択してください。
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF

XAMLに以下のコードを追記します。

MainWindow.xaml
<Grid>
<WindowsFormsHost x:Name="Chart1" />
</Grid>

コードビハインド(MainWindow.xaml.cs)には以下のコードを追加します。

MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
MainWindowViewModel vm = new MainWindowViewModel();
this.DataContext = vm;

Chart1.Child = vm.chart1;
}

ViewModelには以下のコードを追加します。

MainWindowViewModel.cs
public class MainWindowViewModel
{
public Chart chart1;
Title title;
ChartArea chartArea1;
Series series1;

public MainWindowViewModel()
{
chart1 = new Chart();
title = new Title("タイトル");
chartArea1 = chart1.ChartAreas.Add("Area1");
series1 = new Series();

// 数値
Random rdm = new Random();

// X軸表示用の名前
string[] memberList = { "Aさん", "Bさん", "Cさん", "Dさん", "Eさん" };

// グラフの設定
SettingChart();

// グラフ要素の追加
for(int i = 0; i < 5; i++)
{
series1.Points.AddY(rdm.NextDouble());
series1.Points[i].AxisLabel = memberList[i];
}
}

private void SettingChart()
{
// グラフタイトル、軸ラベルの設定
title.DockedToChartArea = "Area1";
chartArea1.AxisX.Title = "X軸ラベル";
chartArea1.AxisY.Title = "Y軸ラベル";

// グラフの種類
series1.ChartType = SeriesChartType.Column;

// ChartにTitle,Seriesを追加
chart1.Titles.Add(title);
chart1.Series.Add(series1);
}
}

以下の棒グラフが表示されます。

画像2

またViewModelにSeriesを追加すると各個人の二つのデータを比較するということも行うことができます。

MainWindowViewModel.cs
        public MainWindowViewModel()
{
chart1 = new Chart();
title = new Title("タイトル");
chartArea1 = chart1.ChartAreas.Add("Area1");
series1 = new Series();
series2 = new Series();

・・・

// グラフ要素の追加
for(int i = 0; i < 5; i++)
{
series1.Points.AddY(rdm.NextDouble());
series2.Points.AddY(rdm.NextDouble());
series1.Points[i].AxisLabel = memberList[i];
}

・・・

// ChartにTitle,Seriesを追加
chart1.Titles.Add(title);
chart1.Series.Add(series1);
chart1.Series.Add(series2);

画像3

またグラフの上に数値や文字を表示する場合はseries1.Points[0から始まるグラフの順番].labelに表示させたい文字を入れることで可能です。
以下はグラフに自身の値をグラフの上に表示させている内容となります。

double value1;
double value2;
// グラフ要素の追加
for(int i = 0; i < 5; i++)
{
value1 = rdm.NextDouble();
value2 = rdm.NextDouble();
series1.Points.AddY(value1);
series1.Points[i].Label = Math.Round(value1,2).ToString();
series2.Points.AddY(value2);
series2.Points[i].Label = Math.Round(value2,2).ToString();
series1.Points[i].AxisLabel = memberList[i];
}

画像4

このグラフを使用する際の注意点ですが、2点あります。

  • コントローラが画面の最前面に表示されるため、グラフの前面に要素を配置することができない。
  • X軸の数を10個以上にすると全てのX軸の各グラフ名が表示されなくなる。

以上の2点です。

特に二つ目の点ですが、例えば以下のように グラフを10人分表示させようとした場合です。

            string[] memberList = { "Aさん", "Bさん", "Cさん", "Dさん", "Eさん","Fさん","Gさん","Hさん","Iさん","Jさん" };

// グラフの設定
SettingChart();

double value1;
double value2;
// グラフ要素の追加
for(int i = 0; i < 10; i++)
{
value1 = rdm.NextDouble();
value2 = rdm.NextDouble();
series1.Points.AddY(value1);
series1.Points[i].Label = Math.Round(value1,2).ToString();
series2.Points.AddY(value2);
series2.Points[i].Label = Math.Round(value2,2).ToString();
series1.Points[i].AxisLabel = memberList[i];
}

表示は以下のようになり、5人の名前しか表示されなくなってしまいます。

画像5

このX軸の表示ですが、10以上からはグラフの数が増えるほど表示するX軸の数も減っていくようです。