在F#中可视化网格中的数据的功能

时间:2011-02-15 05:46:35

标签: f#

我编写了以下函数来查看来自F#interactive的网格中的数据:

open System.Windows.Forms
let grid x = 
   let form = new Form(Visible = true)
   let data = new DataGridView(Dock = DockStyle.Fill)
   form.Controls.Add(data)
   data.DataSource <- x |> Seq.toArray

如何让它适用于1D和2D seqs?例如,grid [1,2,3]grid[(1,0);(2,0);(3,0)];;工作正常但grid [1;2;3];;不起作用。

另一个问题是,为什么我必须添加`|&gt; Seq.toArray才能使它工作?

2 个答案:

答案 0 :(得分:4)

DataGridView使用数据绑定来反映对象属性并将其显示在网格列中(可能自动推断)。 [1,2,3]和[(1,0);(2,0);(3,0)]是元组列表,因此DataGridView可以显示元组组件,相反,[1; 2; 3] - 列表对于整数,它不包含任何公开实际值的属性。

Seq.ToArray是必要的,因为DataSource需要IList,IListSource,IBindingList或IBindingListView(DataGridView.DataSource Property )。 Array实现了IList,F#list - 没有。

答案 1 :(得分:2)

正如desco所解释的那样,DataGridView控件显示对象属性的值。

对于原始类型,这是非常愚蠢的行为 - 例如,如果您指定[ "Hello"; "world!" ]作为数据源,它将显示值Length,其值为5和6.这绝对不是您想要的!

我能找到的最佳解决方案是显式检查字符串和基本类型,并将它们包装在一个只有一个属性的简单类型中(将显示):

type Wrapper(s:obj) = 
  member x.Value = s.ToString()

let grid<'T> (x:seq<'T>) =     
  let form = new Form(Visible = true)    
  let data = new DataGridView(Dock = DockStyle.Fill)    
  form.Controls.Add(data)    
  data.AutoGenerateColumns <- true
  if typeof<'T>.IsPrimitive || typeof<'T> = typeof<string> then
    data.DataSource <- [| for v in x -> Wrapper(box v) |]
  else 
    data.DataSource <- x |> Seq.toArray

grid [ 1 .. 10 ]
grid [ "Hello"; "World" ]