2

Silverlightベースのチャートコントロールからプラグインのないコントロールに移行しようとしています。HighChartsが気に入っており、現在、既存のコードベースへの実装をテストしています。DotNet.HighChartsは、すべてのjavascriptを解析しなくても、チャートをすばやく作成できる候補として見つかりました。

私の質問は、チャートに含まれているときにチャートで使用されるデータをどのように渡すDataTableかです。ここでの回答に続いて、Linqが進むべき道である可能性があることを確認しました。ただし、コードを実際にビルドするのに苦労しています。DotNet.HighChartsのドキュメントには、非静的データをプルする例が示されていません。そのため、幸運はありません。これはこれまでの私のコードの抜粋です:

    Dim da3 As New SqlDataAdapter(sql3, conn3)
    da3.Fill(dt3)
    da3.Dispose()
    conn3.Close()

    Dim chart3 As Highcharts = New Highcharts("chart").InitChart(New Chart() With { _
     .PlotShadow = False _
    }).SetTitle(New Title() With { _
     .Text = "Browser market shares at a specific website, 2010" _
    }).SetTooltip(New Tooltip() With { _
     .Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ this.percentage +' %'; }" _
    }).SetPlotOptions(New PlotOptions() With { _
     .Column = New PlotOptionsColumn With { _
      .AllowPointSelect = True, _
      .Cursor = Cursors.Pointer, _
      .DataLabels = New PlotOptionsColumnDataLabels() With { _
       .Color = ColorTranslator.FromHtml("#000000"), _
       .Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ this.percentage +' %'; }" _
      } _
     } _
    }).SetSeries(New Series() With { _
     .Type = ChartTypes.Column, _
     .Name = "Browser share", _
     .Data = New Helpers.Data(dt3.Select(Function(x) New Options.Point() With {.X = x.periodyear, .Y = x.rate}).ToArray()) _
    })
    ltrChart3.Text = chart3.ToHtmlString()

私は以下をインポートしています:

Imports DotNet.Highcharts
Imports DotNet.Highcharts.Options
Imports System.Data
Imports System.Data.SqlClient
Imports DotNet.Highcharts.Enums
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq

私が得るエラーは.Data = New Helpers.Data(dt3.Select(Function(x) New Options.Point() With {.X = x.periodyear, .Y = x.rate}).ToArray()) _回線上にあります。私はビットLambda expression cannot be converted to 'String' because 'String' is not a delegate typeのエラーとして取得していFunction....rate}ます。

編集: 既存のコードを変更する最初の試み

    Dim chart1 As Highcharts = New DotNet.Highcharts.Highcharts("test")

    Dim series As Series = New Series()
    series.Name = "CO Rates"
    For i As Integer = 0 To dt.Rows.Count - 1
        series.Data = New Helpers.Data(New Object() {dt.Rows(i)("periodyear"), dt.Rows(i)("rate")})
    Next
    chart1.SetSeries(series).InitChart(New Chart() With { _
                                       .Type = ChartTypes.Column})

これにより、2つの列が生成されます。最初の列はx位置0にあり、その値は2011で、もう1つはx位置1にあり、その値は8.3です。これは、dataTableの最後のポイントを取得し、その{x、y}値({2011、8.3})を2つの異なるポイントに変換し、x値とy値が両方ともyであるように見えるため、非常に奇妙です。 {0、x}や{1、y}のような値。私は取得する必要があります:

  • dataTableから取得した{periodyear、rate}の単一シリーズ。
  • 将来的には、dataTableから取得した{periodyear、rate}を使用して、場所ごとにシリーズを作成したいと考えています。

編集2: わかりました。結果をデータディクショナリに変換し、グラフにすべてのポイントを表示させています。現在の唯一の問題はdt.Rows(i)("periodyear")、をDateTime値に変換することです。これはこれまでのコードです(PaseExactメソッドでは失敗します):

Dim series As Series = New Series()
        series.Name = "CO Rates"

        Dim xDate As DateTime
        Dim data As New Dictionary(Of DateTime, Decimal)
        For i As Integer = 0 To dt.Rows.Count - 1
            xDate = DateTime.ParseExact(dt.Rows(i)("periodyear").ToString, "YYYY", Globalization.CultureInfo.InvariantCulture)
            data.Add(xDate, dt.Rows(i)("rate"))
        Next

        Dim chartData As Object(,) = New Object(data.Count - 1, 1) {}
        Dim x As Integer = 0
        For Each pair As KeyValuePair(Of DateTime, Decimal) In data
            chartData.SetValue(pair.Key, x, 0)
            chartData.SetValue(pair.Value, x, 1)
            x += 1
        Next

        Dim chart1 As Highcharts = New Highcharts("chart1").InitChart(New Chart() With { _
         .Type = ChartTypes.Column _
        }).SetTitle(New Title() With { _
         .Text = "Chart 1" _
        }).SetXAxis(New XAxis() With { _
         .Type = AxisTypes.Linear _
        }).SetSeries(New Series() With { _
         .Data = New Helpers.Data(chartData) _
        })

これを文字列値(たとえば1980)だけに変更してから、x軸のAxisTypesをLinearに変更すると、データが表示されます。どういうわけかオフです-1980年は1,980のように見えます。赤ちゃんのステップ...

編集N: これは最終的な解決策です。これは、クリーンアップを使用できるようです。たとえば、X / Y値を入力するためのディクショナリを作成してから、ディクショナリを反復処理してデータをchartDataオブジェクトに追加する必要があるかどうかはわかりません。これは二重の作業のようです。

    Dim stfipsList = (From r In dt.AsEnumerable() Select r("stfips")).Distinct().ToList()
    Dim SeriesList As New List(Of Series)(stfipsList.Count)
    Dim seriesItem(stfipsList.Count) As Series
    Dim xDate As DateTime
    Dim fakeDate As String
    Dim sX As Integer

    sX = 1
    For Each state In stfipsList
        Dim data As New Dictionary(Of DateTime, Decimal)
        Dim stateVal As String = state.ToString
        Dim recCount As Integer = dt.Rows.Count - 1

        For i As Integer = 0 To recCount
            If dt.Rows(i)("stfips").ToString = stateVal Then
                fakeDate = "1/1/" + dt.Rows(i)("periodyear").ToString
                xDate = DateTime.Parse(fakeDate)
                data.Add(xDate.Date, dt.Rows(i)("unemprate"))
            End If
        Next
        Dim chartData As Object(,) = New Object(data.Count - 1, 1) {}
        Dim x As Integer = 0
        For Each pair As KeyValuePair(Of DateTime, Decimal) In data
            chartData.SetValue(pair.Key, x, 0)
            chartData.SetValue(pair.Value, x, 1)
            x += 1
        Next
        seriesItem(sX) = New Series With {
                    .Name = state.ToString, _
                    .Data = New Helpers.Data(chartData)
        }

        SeriesList.Add(seriesItem(sX))

        sX = sX + 1
    Next

    Dim chart1 As Highcharts = New Highcharts("chart1").InitChart(New Chart() With { _
     .Type = ChartTypes.Line _
    }).SetTitle(New Title() With { _
     .Text = "Annual Unemployment Rate" _
    }).SetTooltip(New Tooltip() With { _
     .Formatter = "function() { return '<b>'+ this.series.name + ': ' + Highcharts.dateFormat('%Y', this.x) +'</b>: '+ this.y +' %'; }" _
    }).SetXAxis(New XAxis() With { _
     .Type = AxisTypes.Datetime _
     }).SetYAxis(New YAxis() With { _
       .Min = 0, _
       .Title = New YAxisTitle() With { _
        .Text = "Unemployment Rate", _
        .Align = AxisTitleAligns.High _
      } _
    }).SetSeries(SeriesList.[Select](Function(s) New Series() With { _
                 .Name = s.Name, _
                 .Data = s.Data _
                }).ToArray())

    ltrChart1.Text = chart1.ToHtmlString()
4

2 に答える 2

3

あなたが求めていることを実行する私のコントローラーActionResultsの1つについては、以下を参照してください。これはC#で記述されていますが、VBに簡単に変更できます。求めている情報よりも多くの情報がありますが、VisualStudioでHighchartsを操作するときに他の問題が見える可能性があります。

私がやっていることは、シリーズのリストを作成し、そのリストをハイチャートに渡すことです。この方法の利点は、各シリーズを個別に作成する必要がないことです。

public ActionResult CombinerBarToday(DateTime? utcStartingDate = null,
                                             DateTime? utcEndingDate = null)
        {
            //TEMPORARILY USED TO FORCE A DATE
            //utcStartingDate = new DateTime(2012, 1, 9, 0, 0, 1);
            //utcEndingDate = new DateTime(2012, 1, 9, 23, 59, 59);

            //GET THE GENERATED POWER READINGS FOR THE SPECIFIED DATETIME
            var firstQ = from s in db.PowerCombinerHistorys
                         join u in db.PowerCombiners on s.combiner_id equals u.id
                         where s.recordTime >= utcStartingDate
                         where s.recordTime <= utcEndingDate
                         select new
                         {
                             Combiner = u.name,
                             Current = s.current,
                             RecordTime = s.recordTime,
                             Voltage = s.voltage,
                             Power = s.current * s.voltage
                         };

            //APPLY THE GROUPING
            var groups = firstQ.ToList().GroupBy(q => new
            {
                q.Combiner,
                Date = q.RecordTime.Date,
                Hour = q.RecordTime.Hour
            });

            List<CombinerKwh> stringGroupedKwhlist = new List<CombinerKwh>();

            //CALCULATE THE AVERAGE POWER GENERATED PER HOUR AND ADD TO LIST
            foreach (var group in groups)
            {
                stringGroupedKwhlist.Add(new CombinerKwh(
                                         group.Key.Combiner,
                                         new DateTime(group.Key.Date.Year, group.Key.Date.Month, group.Key.Date.Day, group.Key.Hour, 0, 0),
                                         group.Average(g => g.Power) / 1000d
                                         ));
            }

            //GET A LIST OF THE COMBINERS CONTAINS IN THE QUERY
            var secondQ = (from s in firstQ 
                           orderby s.Combiner 
                           select new
                                {
                                    Combiner = s.Combiner
                                }
                           ).Distinct();

            /* THIS LIST OF SERIES WILL BE USED TO DYNAMICALLY ADD AS MANY SERIES 
             * TO THE HIGHCHARTS AS NEEDEDWITHOUT HAVING TO CREATE EACH SERIES INDIVIUALY */
            List<Series> allSeries = new List<Series>();

            TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

            //LOOP THROUGH EACH COMBINER AND CREATE SERIES
            foreach (var distinctCombiner in secondQ)
            {
                var combinerDetail = from h in stringGroupedKwhlist
                                     where h.CombinerID == distinctCombiner.Combiner
                                     orderby TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone)
                                     select new
                                            {
                                                CombinerID = h.CombinerID,
                                                //CONVERT FROM UTC TIME TO THE LOCAL TIME OF THE SITE
                                                Interval = TimeZoneInfo.ConvertTimeFromUtc(h.Interval,easternZone),
                                                KWH = h.KWH
                                            };

                //REPRESENTS 24 PLOTS FOR EACH HOUR IN DAY
                object[] myData = new object[24];

                foreach (var detailCombiner in combinerDetail)
                {
                    if (detailCombiner.KWH != 0)
                    {
                        myData[detailCombiner.Interval.Hour] = detailCombiner.KWH;
                    }
                }

                allSeries.Add(new Series
                                    {
                                        Name = distinctCombiner.Combiner,
                                        Data = new Data(myData)
                                    });
            }

            Highcharts chart = new Highcharts("chart")
            .InitChart(new Chart { DefaultSeriesType = ChartTypes.Spline })
            .SetTitle(new Title { Text = "Combiner History" })
            .SetXAxis(new XAxis
            {
                Categories = new[] { "0:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM" },
                Labels = new XAxisLabels
                                       {
                                           Rotation = -45,
                                           Align = HorizontalAligns.Right,
                                           Style = "font: 'normal 10px Verdana, sans-serif'"
                                       },
                Title = new XAxisTitle { Text = "Time(Hour)" },
                //Type = AxisTypes.Linear
            })
            .SetYAxis(new YAxis
            {
                //Min = 0,
                Title = new YAxisTitle { Text = "Kwh" }
            })

            .SetSeries(allSeries.Select(s => new Series { Name = s.Name, Data = s.Data }).ToArray());

            return PartialView(chart);
        }
于 2012-04-11T18:12:53.227 に答える
2

ここでは、DataTableからシリーズを作成する方法の例を見つけることができます:http: //dotnethighcharts.codeplex.com/discussions/287106

また、サンプルプロジェクトから、 「ディクショナリからデータをバインドする」および「オブジェクトリストからデータをバインドする」方法を見つけることができます。

于 2012-04-05T21:56:56.103 に答える