Question

With F#, I have used the FreeBase type provider (FSharp.Data) to play around with random data and I'm having trouble visualizing the data that comes back. As I use a (WPF-based) DataGrid and I then populate the ItemsSourcewith a collection of something (Chemical Elements, Stars etc.)

What I'm getting is that when the DataGrid is populated, it 'skips' some properties of that entity that I want to visualize, for example the MainImage which every entity has. Other properties of type IEnumerable of string are also not being visualized.

"not being visualized", means there is no column being created for that property.

in a demo video of F# by Don Syme I see he is using the same thing (a DataGird with WPF) here's the demo: http://www.youtube.com/watch?v=-SGPEUuG1I8 (6 min) I'm not sure whether he was using a customized grid! I had expected, looking at that grid, that it was the default one! as it renders all properties in a non-fancy way!

Code I used to show data with WPF

open System.Windows
open System.Xaml
open System.Windows.Controls
open System.Media

let main = new Window()
main.Height <- 600.0
main.Width <- 500.0

let grid = new DataGrid()
grid.SetValue(DataGrid.FontSizeProperty,20.0)  
main.Content <- grid

let show data =
     match main.IsLoaded with
     | true -> grid.ItemsSource <- data
     | false -> main.Show(); grid.ItemsSource <- data

and I use it like this:

freebase.Commons.Astronomy.Stars |> Seq.take 10 |> show

data retrieval works fine, the grid does not render all stuff! What am I missing here?

Était-ce utile?

La solution

The used ad-hoc data binding grid.ItemsSource <- data silently assumes that the underlying type of items in data collection allows reasonable rendering of each column value into grid cell. But such assumption is too strong to always be the true!

Bound expression freebase.Commons.Astronomy.Stars |> Seq.take 10 has type seq<FreebaseData.ServiceTypes.Astronomy.Astronomy.StarData>. In turn, StarData properties may be anything. For example, property Also known as constitutes IEnumerable by itself, etc. How it should be rendered to a grid cell by default?

If instead we provide a data projection that ensures a default visualization for the binding, then everything would be OK. For example, showing names and distances to five closest to Earth stars can be projected like below:

let astronomy = data.``Science and Technology``.Astronomy
let fiveClosestStars =
    query { for e in astronomy.Stars do
               where e.Distance.HasValue 
               sortBy e.Distance.Value
               take 5
               select (e.Name, e.Distance) } 

where fiveClosestStars now has DataGrid-palatable type Linq.IQueryable<string * Nullable<float<Data.UnitSystems.SI.UnitNames.metre>>>. Then binding

grid.ItemsSource <- fiveClosestStars 

yields the expected visual experience

Sun                     149597987918.808
Proxima Centauri 4.014161112E+16
Wolf 359              7.3747752E+16
Sirius                   8.1461952E+16
Altair                    1.58295384E+17

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top