图表绑定到非基本类型

时间:2017-10-17 15:41:16

标签: c# .net winforms data-binding charts

我有一个C#.NET Windows Forms应用程序,使用的图表包含许多系列。我有一个物理设备存储读数,当我下载读数时,我希望图表填写详细信息。

我已经在软件中创建了可量化值(例如温度)的类型,可以根据位置使用不同的单位,允许我为显示单位设置用户,并且只需处理背景中的所有内容而无需关心,以及当它显示给用户时,它是在正确的单位。

C#.NET Charting.Series类非常严格,当尝试使用绑定数组进行绘制时,它会抛出一个带有以下语句的ArgumentExeption:“系列数据点不支持Units类型的值.Temperature只有这些类型的值可以使用:Double,Decimal,Single,int,long,uint,ulong,String,DateTime,short,ushort“。

Temperature类型有一个名为Value的属性,它是一个double,也可以隐式转换为double,但这似乎并不重要。我希望有一种方法可以绑定它,以便它在每次请求结果数组中的值时进行转换,这样它就可以正确地绘制图形,任何人都知道这是怎么回事  可能会完成吗?

我希望避免使用LogItem [],然后再使用辅助双[]进行转换。

private LogItem[] results;

private async void GraphPage_Load(object sender, EventArgs e) {
    var count = await device.LogCount.Read(CancelToken);
    results = new LogItem[count];
    graph.DataSource = results;
    graph.Series[0].XValueMembers = nameof(LogItem.DateTime); //Type is System.DateTime
    graph.Series[0].YValueMembers = nameof(LogItem.Temperature); //Type my library, Units.Temperature

    var prog = new Progress<double>();
    prog.ProgressChanged += (sender2, e2) => {
        BeginInvoke(new Action(() => {
            progBar.Value = results.Count(log => !Equals(log, LogItem.Empty));
            CheckEmptyPoints(); //Sets or clears Points[x].IsEmpty;
            graph.Invalidate(); //Force graph to draw new results, maybe a better way of doing this?
        }));
    };
    await device.DownloadLogs(CancelToken, results, prog); //Takes output buffer and IProgress to report more data has been downloaded.
}

2 个答案:

答案 0 :(得分:2)

您可以使用linq将结果整形为图表友好的形状。例如:

%f[%D]

var list = results.Select(x => new { X = x.DateTime, Y = x.Temprature.Value }).ToList(); this.chart1.DataSource = list; this.chart1.Series[0].XValueMember = "X"; this.chart1.Series[0].YValueMembers = "Y"; X只是占位符,您可以使用YDateTime或任何合适的标签。

答案 1 :(得分:1)

非常感谢Reza Aghaei寻求帮助。

Linq语句确实提供了提供转换函数的答案,但只需稍加调整就可以创建一个新数组,并在每次刷新时重新绑定。

解决方案是使用Charting.DataPointsCollection.DataBind(IEnumerable dataSource, string xField, string yField, string otherFields)绑定到数据。但是要使用Linq语句来创建要在数据绑定中使用的IEnumerable对象,并且在每次调用MoveNext时,此IEnumerable将从数组中获取数据并转换为图表。

// IEnumerable<LogItem>.Select(...) creates an IEnumerable which references the array,
//   and performs the selection and conversion on each call to MoveNext().

graph.Series[0].Points.DataBind(
    results.Select(l => new { X = l.DateTime, Y = l.OilCondition.Value }),
    "X",
    "Y",
    string.Empty);

编辑:以上操作正常,但根据Points.DataBind(,,,)的文档,评估只执行一次,因此每次都需要调用DataBind(,,,)方法。