2017-10-17 105 views
1

我有一個C#.net Windows窗體應用程序使用圖表與一系列行系列。我有一個存儲讀數的物理設備,當我下載讀數時,我希望圖表填寫詳細信息。圖表綁定到非原始類型

我在軟件中創建了可根據位置使用不同單位的可量化值(如溫度)的類型,允許我爲顯示單位設置用戶設置,並且只處理背景中的所有內容而不關心,當它顯示給用戶時,它在正確的單位。

C#.NET Charting.Series類非常嚴格,當試圖使用綁定數組進行繪製時,它會引發一個帶有以下語句的ArgumentExeption:「系列數據點不支持Units.Temperature類型的值,只有這些類型的值可以使用:Double,Decimal,Single,int,long,uint,ulong,String,DateTime,short,ushort「。

溫度類型有一個名爲Value的屬性,它是一個double,也可以隱式轉換爲double,但這似乎並不重要。我希望有一種方法來綁定它,以便它在每次請求結果數組中的值時進行轉換,以便它可以正確地繪製圖形,任何人都知道可以如何完成這個 ?

我希望避免需要LogItem [],然後是一個輔助double [],只是爲了轉換。

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

回答

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(,,,)方法確實需要每次都被稱爲。

+0

不客氣:) –

+0

只需確認一切正常,然後再標記答案。 – TheBeardedQuack

2

您可以使用linq將結果塑造成圖表友好的形狀。例如:

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"; 

XY只是持有人的地方,你可以使用DateTimeTempratue或任何適合的標籤。

+0

我確實提到過我希望避免需要第二個緩衝區,並且使用Linq可能會更糟,因爲它會繼續重新分配內存。我可以修改這些機制,使用Points.Insert()使用Series的內部列表並刪除數據綁定。但很高興知道如何做到這一點。 – TheBeardedQuack

+0

對於這樣一個簡單的查詢,通常內存不會成爲問題。但是您也可以使用循環和'chart1.Series [0] .Points.AddXY(x,y);'爲圖表添加點。 –

+0

問題是,我正在下載潛在的數千條記錄,這些記錄應該將該對象放置到.NET中的LOH中。儘管實際上它始終保持相同的大小,因此已知的LOH問題不應該發生。 我需要更多地瞭解Linq的工作原理,因爲我可能會根據您的建議想到一個解決方案。 – TheBeardedQuack