セージ の メモ書き

メモこそ命の恩人だ

Chart で グラフ表示 してみる

Chart クラス

Chart Class (System.Windows.Forms.DataVisualization.Charting) | Microsoft Docs

こんな感じ。

<!-- ユーザーコントロール(Chartコントロールをラップ) -->
<UserControl x:Class="WpfApp1.ChartUserControl"
             ...
             xmlns:visualization="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization">

    <WindowsFormsHost>
        <!-- Chartコントロール -->
        <visualization:Chart x:Name="Chart1" GetToolTipText="Chart1_GetToolTipText" />
    </WindowsFormsHost>
</UserControl>
// コードビハインド(コンストラクタ)
public ChartUserControl()
{
    InitializeComponent();

    //-------------------
    // 表示設定
    //-------------------
    // 初期化
    this.Chart1.ChartAreas.Clear();
    this.Chart1.Series.Clear();
    this.Chart1.Titles.Clear();
    this.Chart1.Legends.Clear();

    // フォント設定
    var chartFont = new System.Drawing.Font("Meiryo UI", 14.0F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);

    // 表示エリア設定
    var chartArea = new ChartArea
    {
        BackColor = System.Drawing.Color.LightGray,
        BackGradientStyle = GradientStyle.TopBottom,
    };
    chartArea.AxisX.Title = "時間";   // X軸タイトル
    chartArea.AxisY.Title = "発生回数"; // Y軸タイトル
    chartArea.AxisY.TextOrientation = TextOrientation.Stacked;  // Y軸タイトルテキスト配置:スタック
    chartArea.AxisX.TitleFont = chartFont;  // X軸フォント
    chartArea.AxisY.TitleFont = chartFont;  // Y軸タイトル
    chartArea.AxisX.Minimum = 0;   // X軸最小値
    chartArea.AxisX.Maximum = 23;   // X軸最大値
    chartArea.AxisX.Interval = 1.0; // X軸間隔
    chartArea.AxisX.MajorGrid.Enabled = false;  // X軸罫線:なし
    chartArea.AxisY.MajorGrid.LineColor = System.Drawing.Color.Gray;    // Y軸罫線色
    chartArea.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dot;   // Y軸罫線スタイル:ドット
    chartArea.Area3DStyle.Enable3D = false; // 3D効果:なし
    this.Chart1.ChartAreas.Add(chartArea);

    // 座標データ設定
    var series = new Series
    {
        Name = "ログ1",    // 凡例タイトル
        ChartType = SeriesChartType.Line,    // グラフタイプ:線グラフ
        MarkerStyle = MarkerStyle.Circle,    // マーカー:丸
        Color = System.Drawing.Color.Blue,  // グラフ色:青
        Font = chartFont,
    };
    this.Chart1.Series.Add(series);

    // タイトル設定(不要ならコメントアウト)
    var title = new Title("ログデータ");
    this.Chart1.Titles.Add(title);

    // 凡例設定(不要ならコメントアウト)
    var legend = new Legend();
    this.Chart1.Legends.Add(legend);
}
// コードビハインド(座標データをバインディング可能にする。)
public List<Point> PointList
{
    get { return GetValue(PointListProperty) as List<Point>; }
    set { SetValue(PointListProperty, value); }
}
public static readonly DependencyProperty PointListProperty = DependencyProperty.Register(
        "PointList",
        typeof(List<Point>),
        typeof(ChartUserControl),
        new PropertyMetadata(null, OnPointListChanged)
    );
private static void OnPointListChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    if (!(sender is ChartUserControl control)) return;
    if (!(e.NewValue is List<Point> pointList)) return;
    if (pointList.Count == 0) return;

    // 座標データ設定
    var tempSeries = control.Chart1.Series.First();
    tempSeries.Points.Clear();
    foreach (var point in pointList) tempSeries.Points.AddXY(point.X, point.Y);
}
// コードビハインド(ツールチップ表示用)
private void Chart1_GetToolTipText(object sender, System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs e)
{
    if (e.HitTestResult.ChartElementType != ChartElementType.DataPoint) return;
    var pointIndex = e.HitTestResult.PointIndex;
    var point = e.HitTestResult.Series.Points[pointIndex];
    e.Text = $"{point.XValue}時台 -> {point.YValues[0]}回";
}


上記のユーザーコントロールを使用し、ログデータをグラフ表示してみる。
ViewModel で以下を実行する。

// ユーザーコントロールにバインディングするプロパティ
public List<Point> PointList
{
    get { return pointList; }
    set { SetProperty(ref pointList, value); }
}
private List<Point> pointList = new List<Point>();
// サンプルデータ
var logDataList = new[]
{
    new { Time = new DateTime(2019,1,1,8,0,0), Message = "データ1"},
    new { Time = new DateTime(2019,1,1,8,10,0), Message = "データ2"},
    new { Time = new DateTime(2019,1,1,8,20,0), Message = "データ3"},
    new { Time = new DateTime(2019,1,1,9,0,0), Message = "データ4"},
    new { Time = new DateTime(2019,1,1,9,30,0), Message = "データ5"},
    new { Time = new DateTime(2019,1,1,10,0,0), Message = "データ6"},
};

//  時間毎のログ発生回数を集計 (0時~23時)
var timeCountList = Enumerable.Repeat(0, 24).ToList();
foreach (var logData in logDataList) timeCountList[logData.Time.Hour]++;

// 座標データ設定
var tempPointList = new List<Point>();
foreach (var (count, hour) in timeCountList.Select((count, hour) => (count, hour)))
{
    tempPointList.Add(new Point(hour, count));
}
                    
// グラフ反映
PointList.Clear();
PointList = tempPointList;

View はこんな感じ。

<!-- ViewModel の処理でグラフ表示できたことを確認。 -->
<local:ChartUserControl PointList="{Binding PointList}" />

ChartType 列挙型

SeriesChartType Enum (System.Web.UI.DataVisualization.Charting) | Microsoft Docs

一部をメモする。詳細は上記サイトを参照。

列挙値 内容
Line 折れ線グラフ
Column 縦棒グラフ
Bar 横棒グラフ
Area 面グラフ


以上😃