F# Silverlight:使用PropertyPath或其他方法按顺序绑定列

发布于 2024-10-07 04:08:23 字数 3879 浏览 2 评论 0原文

我正在尝试动态填充自动完成的值。我得到一个 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])

对我来说没有多大意义...

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

                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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一城柳絮吹成雪 2024-10-14 04:08:23

我实际上不知道,但我会

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

根据阅读以下内容尝试(例如将其放在带引号的字符串中):

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

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

会发光的星星闪亮亮i 2024-10-14 04:08:23

采用这个:
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

我想这是一个不错的解决方案。希望大脑(是拼写错误还是神的干预)也能发挥作用,它更加直接。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文