F#Silverlight:使用PropertyPath或其他方法通常绑定列

时间:2010-12-07 21:53:50

标签: silverlight xaml binding f#

我正在尝试动态填充自动填充的值。我得到了一个SearchResult元组列表,其中每个元组的第一个字符串是KEY,字符串列表是每列需要显示的显示文本。假设是任何SearchResult列表中的所有行都将在显示文本列表中包含相同数量的项目。我真的希望能够按顺序绑定到显示文本列表的值......

简化示例将采用以下数据:

 [
     ("MSFT.OQ", ["MSFT.OQ"; "Microsoft"; "Nasdaq"]) ;
     ("GOOG.OQ", ["GOOG.OQ"; "Google"; "Nasdaq"]);
 ]

并显示:

MSFT.OQ         Microsoft       Nasdaq
GOOG.OQ         Google          Nasdaq

但我看到的是:

["MSFT.OQ"; "Microsoft"; "Nasdaq"]     ["MSFT.OQ"; "Microsoft"; "Nasdaq"]    ["MSFT.OQ"; "Microsoft"; "Nasdaq"]
["GOOG.OQ"; "Google"; "Nasdaq"]        ["GOOG.OQ"; "Google"; "Nasdaq"]       ["GOOG.OQ"; "Google"; "Nasdaq"]

整个列表以每列结尾,所以我认为我的绑定已关闭。

我的示例代码(试图从更复杂的模型中简化):

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

                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

谢谢...


令人惊讶的是(至少对我来说)这些返回相同的结果:

   binding.Path <- PropertyPath([])
   binding.Path <- PropertyPath("")
   binding.Path <- PropertyPath([0].[0])

对我来说没什么意义......

2 个答案:

答案 0 :(得分:0)

我实际上并不知道,但我会尝试

binding.Path <- PropertyPath(sprintf "[%d]" i)

(例如,将其置于带引号的字符串中),基于以下内容:

http://msdn.microsoft.com/en-us/library/cc645024%28VS.95%29.aspx

答案 1 :(得分:0)

采用这个: http://www.scottlogic.co.uk/blog/colin/2009/04/binding-a-silverlight-datagrid-to-dynamic-data-via-idictionary/

工作:

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()

并在我的代码中用

替换绑定
let binding = System.Windows.Data.Binding()
binding.Path <- PropertyPath([])
binding.Converter <- RowIndexConverter()
binding.ConverterParameter <- i

我想这是一个很好的解决方案。希望大脑(这是一个错字或神圣干预)也会起作用,它更直接。