C#プログラミング

【C#】WPFで円グラフを使いこなす【チャート】

円グラフを使いこなす記事のアイキャッチ画像 C#

C#(WPF)で円グラフを描く際に、見やすくする方法を自分なりにまとめてみました。具体的にな内容は以下になります。

  • 開始位置の角度調整
  • 要素内に情報表示

ちなみにまずWPFにおけるグラフの描画方法を知りたいという方はこちらの過去記事を参照ください。WPFでのグラフ描画までの手順・サンプルコードがあります。

スポンサーリンク

とりあえず円グラフを描画してみる

過去記事のコードをそのまま流用し、円グラフを描画すると下画像のような感じになります。
ViewModel内のChartType指定の部分を「SeriesChartType.Pie」にすると円グラフが表示されます。

デフォルト設定で表示される円グラフの様子

デフォルトでは開始位置は時計の3時の位置になっています。なぜなのか、、、?
あとグラフ上にも情報を表示したいですね。

スポンサーリンク

今回扱う見やすくする方法

一番最初に述べた通り、以下点を改善して見やすくします。

  1. 要素の開始位置を真上(12時)にする
  2. 要素内に情報を表示する

2.に関しては「凡例」との兼ね合いもありますが、今回は両方表示します。

スポンサーリンク

サンプルコード

グラフの様子と仕様

今回描画する円グラフは以下のようになります。

見やすくした円グラフの様子

「Add」ボタンを押すと要素が追加され、「Clear」ボタンを押すと要素が全てクリア(=リセット)されます。追加される要素(値)の大きさはランダム値(0~1)です。

ソースコード

MVVM形式で書いています。要所はViewModelに書いてありますので他の形式の方はそこを参考にしてみてください。

グラフ表示の本質に触れない部分(コマンドや通知機能)は省略しています。

View(XAML)View(コードビハインド)は以下の通り。

<Window x:Class="Graph_inWPF_01.Views.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Graph_inWPF_01" Height="300" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        
        <Button Grid.Row="0" Grid.Column="0" Margin="2" Content="Add" Command="{Binding AddBtn_Pushed}" />
        <Button Grid.Row="1" Grid.Column="0" Margin="2" Content="Clear" Command="{Binding ClearBtn_Pushed}" />
        
        <!--グラフ-->
        <WindowsFormsHost Name="Chart1v" Grid.Row="0" Grid.Column="1" Grid.RowSpan="3" Margin="10" />
    </Grid>
</Window>
namespace Graph_inWPF_01.Views
{
    public partial class MainView : Window
    {
        public MainView()
        {
            InitializeComponent();

            MainViewModel vm = new MainViewModel();
            this.DataContext = vm;

            //Chart関連
            Chart1v.Child = vm.chart1;
        }
    }
}

ViewModelは以下の通り。
変数cntは要素の番号、valが実際の要素の値になります。要素内情報表示は番号と値にしています。

namespace Graph_inWPF_01.ViewModels
{
    public class MainViewModel:INotifyPropertyChanged
    {
        //チャート関連
        public Chart chart1;
        Title title;
        ChartArea chartarea1;
        Series series1;
        Legend legend1;

        //チャート用パラメータ
        int cnt = 0;
        Random rdm;

        //コマンド
        public ICommand AddBtn_Pushed { get; set; }
        public ICommand ClearBtn_Pushed { get; set; }

        public MainViewModel()
        {

            //チャート関連
            chart1 = new Chart();
            title = new Title("グラフタイトル");
            chartarea1 = chart1.ChartAreas.Add("Area1");
            series1 = new Series();
            legend1 = new Legend();


            //チャート初期化
            ChartInitialize();

            //コマンド
            AddBtn_Pushed = new RelayCommand(Add_cmd);
            ClearBtn_Pushed = new RelayCommand(ChartClear_cmd);

            //他(要素生成用)
            rdm = new Random();
        }


        //チャート初期化
        private void ChartInitialize()
        {
            //ChartAreaの設定(グラフタイトル)
            title.DockedToChartArea = "Area1";
            
            //Seriesの初期設定------------------------------------------
            //グラフの種類指定
            series1.ChartType = SeriesChartType.Pie;
            //①要素の開始位置を設定(デフォルトは0で、時計回りに角度を指定できる)
            series1["PieStartAngle"] = "270";

            //ChartにTitle,Series,Legend(凡例)を追加
            chart1.Titles.Add(title);
            chart1.Series.Add(series1);
            chart1.Legends.Add(legend1);
        }

        //コマンド(チャート要素追加)
        private void Add_cmd()
        {
            //グラフに追加する値を生成(ランダム)
            double val = Math.Round(rdm.NextDouble(), 2);

            //要素(値)を追加する
            series1.Points.Add(val);
            //②要素内にラベル表示をする
            series1.Points[cnt].Label = "要素" + (cnt + 1).ToString() + "(" + val.ToString() + ")";

            //要素番号を増やす
            cnt++;
        }

        //コマンド(チャート要素クリア)
        private void ChartClear_cmd()
        {
            series1.Points.Clear();
            cnt = 0;
        }
    }
}

凡例のテキスト」と「要素内情報(Points[].Label)」はリンクしているようで同じテキスト表示になっていますね。

角度調整の方法を調べるのに結構時間かかりましたが、目的は達成できました。円グラフ以外のドーナツ型グラフなどにも有効です。
要素の数によっては他の表現のほうが見やすいこともありそうですね。

コメント

タイトルとURLをコピーしました