我们正试图从基于Silverlight的图表控件转向更多无插件的控件。我们喜欢HighCharts,现在正在测试将它实现到我们现有的代码库中。 我们已经发现DotNet.HighCharts可以快速创建图表,而无需解析所有的JavaScript。
我的问题是,如果数据包含在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()) _
行。我在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,另一列位于x位置1,其值为8.3。这是非常奇怪的,因为它在我看来它正在取dataTable中的最后一点,然后将其{x,y}值({2011,8.3})分成两个不同的点,其中x和y值都是y像{0,x}和{1,y}这样的值。 我需要得到:
编辑2:
好吧,我把结果转换为datadictionary,我得到的图表显示所有点。现在只有问题是将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()
答案 0 :(得分:3)
请参阅下面的我的控制器ActionResults之一,它可以执行您的要求。它是用C#编写的,但可以很容易地修改为VB。有比您要求的信息更多的信息,但在Visual Studio中使用Highcharts时,它可能会提供其他问题的可见性。
我正在做的是创建一个Series列表,然后将列表传递给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);
}
答案 1 :(得分:2)
在这里,您可以找到如何从DataTable创建系列的示例: http://dotnethighcharts.codeplex.com/discussions/287106
同样来自sample project你可以找到如何“从字典中绑定数据”和“从对象列表中绑定数据”