F# Silverlight: using PropertyPath or other method to bind columns ordinally
I am trying to populate the values of an autocomplete dynamically. I get a list of SearchResult tuples, where per tuple the first string is the KEY and the list of strings are the display text that need to display per column. The assumption is that of any list of SearchResult all rows will contain the same amount of items in the display text list. I really would like to be able to bind to the values of the display text list by ordinal...
a simplified example would take data like this:
[
("MSFT.OQ", ["MSFT.OQ"; "Microsoft"; "Nasdaq"]) ;
("GOOG.OQ", ["GOOG.OQ"; "Google"; "Nasdaq"]);
]
and display:
MSFT.OQ Microsoft Nasdaq
GOOG.OQ Google Nasdaq
but I am seeing something like:
["MSFT.OQ"; "Microsoft"; "Nasdaq"] ["MSFT.OQ"; "Microsoft"; "Nasdaq"] ["MSFT.OQ"; "Microsoft"; "Nasdaq"]
["GOOG.OQ"; "Google"; "Nasdaq"] ["GOOG.OQ"; "Google"; "Nasdaq"] ["GOOG.OQ"; "Google"; "Nasdaq"]
The entire list is ending up in each column, so I am thinking my binding is off.
My sample code (attempted to be simplified from a more complex model):
type SearchResult = (string * string list)
type Template() as this =
inherit Page
[<DefaultValue>]
val mutable acbTickerSearch : AutoCompleteBox
do
this.acbTickerSearch = this ? acbTickerSearch
this.display Some(this.getSampleResults())
member private this.getSampleResults() =
[
("MSFT.OQ", ["MSFT.OQ"; "Microsoft"; "Nasdaq"]) ;
("GOOG.OQ", ["GOOG.OQ"; "Google"; "Nasdaq"]);
("IBM", ["IBM"; "International Business Machines"; "NYSE"]);
("AKAM.OQ", ["AKAM.OQ"; "Akamai"; "Nasdaq"]);
]
member this.display (results: SearchResult list option) =
let build(result: SearchResult) =
// if we haven't built the bindings yet lets do so
if this.tickerSearchDataGrid = null then
// create a grid
this.tickerSearchDataGrid <- new DataGrid()
this.tickerSearchDataGrid.AutoGenerateColumns <- false
开发者_Python百科 let addColumn i (item: string) =
let col = new DataGridTextColumn()
let binding = System.Windows.Data.Binding()
// LOOK HERE: attempting to bind to an indexer... not working so well,,
binding.Path <- PropertyPath([i])
col.Binding <- binding
this.tickerSearchDataGrid.Columns.Add(col)
i + 1
result
// the second portion of the tuple, is a list that
// needs to be displayed, wach item in its own column
|> snd
// should probably be List.iteri
|> List.fold addColumn 0
// don't need this with List.iteri
|> ignore
let displayResults (resultLst: SearchResult list) =
// create a list of lists, throwing away the "key" portion of the tuple
// potentially a bug I need toget around...
let lst =
resultLst
|> List.map (fun (r: SearchResult) -> snd r)
// bind to the data source
this.tickerSearchDataGrid.ItemsSource <- lst
this.tickerSearchDataGrid.HeadersVisibility <- DataGridHeadersVisibility.None
this.acbTickerSearch.ItemsSource <- [this.tickerSearchDataGrid]
this.acbTickerSearch.IsDropDownOpen <- true
match results with
| None -> ()
| Some r ->
// set the number of columns based on the results,
// assume all tuples will have an equal number of values,
// we only need the head to determine the columns then
build <| List.head r
// bind the results
displayResults r
Thank you...
suprisingly (to me at least) these return the same results:
binding.Path <- PropertyPath([])
binding.Path <- PropertyPath("")
binding.Path <- PropertyPath([0].[0])
not making much sense to me...
I don't actually know, but I would try
binding.Path <- PropertyPath(sprintf "[%d]" i)
(e.g. put it inside a quoted string), based on reading this:
http://msdn.microsoft.com/en-us/library/cc645024%28VS.95%29.aspx
adopting this: http://www.scottlogic.co.uk/blog/colin/2009/04/binding-a-silverlight-datagrid-to-dynamic-data-via-idictionary/
worked:
type RowIndexConverter() =
interface IValueConverter with
member this.Convert(value, targetType, parameter, culture) =
let row = value :?> string list ;
let index: int = parameter :?> int;
row.[index] :> obj;
member this.ConvertBack(value, targetType, parameter, culture) = raise <| NotImplementedException()
and in my code replace the binding with
let binding = System.Windows.Data.Binding()
binding.Path <- PropertyPath([])
binding.Converter <- RowIndexConverter()
binding.ConverterParameter <- i
I guess it is an ok solution. Hopefully Brains (was that a typo or divine intervention) will work as well, its a lot more straight forward.
精彩评论