开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜