旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【C#】動的にChartを追加する

円グラフを描きたいけれども、アプリを動作させてからでないと何個の円グラフを描くか決めれない状況のため、動的にChartを追加する方法を調べました。グラフを描くために使ったライブラリはLiveCharts.Wpfになります。

まずはxamlです。以下で定義したStackPanel1に動的にChartを追加します。

<Window x:Class="LiveChartsExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LiveChartsExample"
        xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Name="StackPanel1" Orientation="Horizontal">
    </StackPanel>
</Window>


次にC#側のソースです。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

using LiveCharts;
using LiveCharts.Wpf;

namespace LiveChartsExample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var random = new Random();
            // 例として円グラフを4つ描いてみる
            for (int i = 0; i < 4; ++i)
            {
                // グリッドの定義
                var grid = new Grid();
                grid.Width = 150;
                var row1 = new RowDefinition();
                row1.Height = new GridLength(30);
                var row2 = new RowDefinition();
                row2.Height = new GridLength(150);
                grid.RowDefinitions.Add(row1);
                grid.RowDefinitions.Add(row2);

                // 表題用TextBlock
                var title = new TextBlock();
                title.Text = "Chart" + i.ToString();
                title.FontSize = 20;
                title.Foreground = new SolidColorBrush(Colors.Black);
                title.HorizontalAlignment = HorizontalAlignment.Center;

                // 円グラフの定義
                var chart = new PieChart();
                chart.Name = "Chart" + i.ToString();
                chart.StartingRotationAngle = 0;
                chart.Width = 150;
                chart.Height = 150;
                chart.MouseDown += Chart_MouseDown;
                chart.LegendLocation = LegendLocation.Bottom;

                var series1 = new PieSeries()
                {
                    Title = "A",
                    Values = new ChartValues<int> { random.Next(100) },
                    DataLabels = true,
                    LabelPoint = point => string.Format("{0} ({1:P})", point.Y, point.Participation)
                };
                var series2 = new PieSeries()
                {
                    Title = "B",
                    Values = new ChartValues<int> { random.Next(100) },
                    DataLabels = true,
                    LabelPoint = point => string.Format("{0} ({1:P})", point.Y, point.Participation)
                };
                chart.Series.Add(series1);
                chart.Series.Add(series2);

                // グリッドの0行目に表題、1行目にグラフを設置
                Grid.SetRow(title, 0);
                Grid.SetRow(chart, 1);
                grid.Children.Add(title);
                grid.Children.Add(chart);

                // スタックパネルにグリッドを追加
                StackPanel1.Children.Add(grid);
            }
        }

        private void Chart_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            PieChart chart = sender as PieChart;

            // 以下チャートがクリックされた時の動作を書く
        }

    }
}

上記を実行すると以下のように円グラフが4つ表示されます。 f:id:ni4muraano:20180513121255p:plain
それにしてもLiveChartsはグラフに表題を付けるのにこんな書き方をしないとダメなのでしょうか。PieChartクラスにTitleというプロパティが無く、サイトの例を見ても分からなかったので今回はGridにTextBlockとChartを置くことでTextBlockがChartのタイトルに見えるようにしています。