2012-04-05 3 views
2

Silverlightベースのチャートコントロールからプラグインレスのコントロールに移行しようとしています。 HighChartsが好きで、既存のコードベースへの実装をテストしています。 DotNet.HighChartsは、すべてのjavascriptを解析することなく、迅速にチャートを作成できる可能性があると判明しました。DotNet.HighChartsライブラリを使用してWebサービスからのDataTable結果に基づくグラフを作成する

私の質問は、DataTableに含まれている場合、チャートで使用するデータをどのように渡しますか?答えがhereに続いて、私は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()) _ライン上にあります。私はFunction....rate}ビットで私のエラーとしてLambda expression cannot be converted to 'String' because 'String' is not a delegate typeを取得しています。

EDIT:既存のコードを修正することで 最初の試み

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}) 

これはちょうど最初のx位置0にある2つの列を生成し、その値2011であり、他方はx位置1にあり、その値は8.3です。これは、dataTableの最後の点を取って、その{x、y}の値({2011、8.3})を2つの異なる点にするように見えるので、非常に奇妙です.xとyの両方の値がy {0、x}や{1、y}のような値です。 私は取得する必要があります:

  • {periodyear、rate}をdataTableから取得した単一のシリーズです。
  • 将来的には、各場所の系列を、 {periodyear、rate}というdataTableから取得したいと考えています。

EDIT 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を変更した場合表示データ。何とかしていない - 1980年は1,980のように見える。ベビーステップ...

EDIT 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() 

答えて

2

あなたはデータテーブルから、一連作成する方法の例を見つけることができますから。また http://dotnethighcharts.codeplex.com/discussions/287106

sample projectあなたは見つけることができますどのように「オブジェクト・リストからバインドデータ」「バインド辞書からデータ」と

+0

私が行っているこの種のディスカッションポストを見てください。これを試してみると、データポイントごとに異なるx個の系列が得られますか?私はプロットする複数のシリーズを持っているときにこのようにしたい理由があるのですが、結果セットの各行のグラフにperiodyearとrateの値を1つのセットとして渡したいだけです。私は投げているものがWith {}構文であると思います。私は自分のコードを深く見ていきます。私は私の質問を私の非実践的な試みで更新しました。 – wergeld

3

あなたが求めているものを実行する私のコントローラのActionResultsについて下記を参照してください。それはC#で書かれていますが、VBに十分に簡単に修正することができます。あなたが求めているものよりも多くの情報がありますが、Visual Studioでハイチャートを使って作業するときに、他の問題を可視化する可能性があります。

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

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); 
     } 
関連する問題