2015-03-31 51 views
0

我试图创建一个图表在winforms中,数据绑定到内存中的列表,并获取动态更新列表更改。这里是我的代码:F#Winforms图表异步更新

open System 
open System.Linq 
open System.Collections 
open System.Collections.Generic 
open System.Drawing 
open System.Windows.Forms 
open System.Windows.Forms.DataVisualization 
open System.Windows.Forms.DataVisualization.Charting 

let link = new LinkedList<double>() 
let rnd = new System.Random() 
for i in 1 .. 10 do link.AddFirst(rnd.NextDouble()) |> ignore 
let series = new Series() 
let chart = new System.Windows.Forms.DataVisualization.Charting.Chart(Dock = DockStyle.Fill, Palette = ChartColorPalette.Pastel) 

series.Points.DataBindY(link) 

let form = new Form(Visible = true, Width = 700, Height = 500) 
form.Controls.Add(chart) 

let formloop = async { 
    while not chart.IsDisposed do 
     link.AddFirst((new System.Random()).NextDouble()) |> ignore 
     link.RemoveLast() 
} 
do 
    Async.StartImmediate(formloop) 
    Application.Run(form) 

Console.WriteLine("Done") 
Console.ReadLine() |> ignore 

异步似乎工作,但图表从不显示任何东西。它只是显示一个空白窗口。我究竟做错了什么?

回答

3

LinkedList<T>无法表示它已被更新,因此Chart无法知道何时重新绘制自己。

为了使数据绑定更新视图,源列表必须实现IBindingList并在内容更改时引发适当的事件。

另外,我必须指出,从非UI线程直接访问UI属性/方法(例如代码中的chart.IsDisposed)是危险的。在WinForms中,这个限制实际上很少实际执行,所以有时这似乎工作正常,只能在客户机器上稍后崩溃而无法连接调试器。

0
  • 您需要将该系列添加到图表的SeriesCollection

    chart.Series.Add series 
    
  • 你需要构建一个图表区域,并将其添加到图表的ChartAreaCollection

    let area = new ChartArea() 
    chart.ChartAreas.Add area 
    
  • 您需要确保在设置图表和窗体后调用数据绑定方法。

    ... 
    form.Controls.Add chart 
    series.Points.DataBindY link 
    
  • 而且现在也没有办法传达给该系列的DataPointCollection您绑定的集合的变化,如Fyodor Soikin's answer提及。我不太确定IBindingList是否合适。虽然可以挂钩ListChanged事件,但我们也可以直接操纵系列的DataPointCollection

    let formloop = async{ 
        while not chart.IsDisposed do 
         series.Points.RemoveAt 0 
         series.Points.AddY(rnd.NextDouble()) |> ignore 
         do! Async.Sleep 100 } 
    
  • 最后,我想指出,这个contribution由约翰·阿特伍德其通过不会忽略费奥多尔提出两点;数据绑定问题(不使用它)和UI线程安全问题。