我编写了以下函数来查看来自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才能使它工作?
答案 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" ]