Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF中具有丰富单元格内容的多列列表_Wpf_F# - Fatal编程技术网

WPF中具有丰富单元格内容的多列列表

WPF中具有丰富单元格内容的多列列表,wpf,f#,Wpf,F#,我正在尝试使用WPF和F#编写一个自动化测试工具。我希望将聚合测试结果显示为多列列表中的行。理想情况下,我希望在每个单元格中显示丰富的内容,例如使用颜色突出显示特定测试的问题,或通过工具提示提供详细信息。但是,我不知道如何将比普通字符串更丰富的内容放入多列ListView 此外,我不喜欢XAML或数据绑定,更喜欢编写普通的F#代码。我能编写的显示多列WPFListView的最简单程序是: open System.Windows let gridView = Controls.GridView(

我正在尝试使用WPF和F#编写一个自动化测试工具。我希望将聚合测试结果显示为多列列表中的行。理想情况下,我希望在每个单元格中显示丰富的内容,例如使用颜色突出显示特定测试的问题,或通过工具提示提供详细信息。但是,我不知道如何将比普通字符串更丰富的内容放入多列
ListView

此外,我不喜欢XAML或数据绑定,更喜欢编写普通的F#代码。我能编写的显示多列WPF
ListView
的最简单程序是:

open System.Windows

let gridView = Controls.GridView()
let listView = Controls.ListView(View=gridView)

type SystemParams = { Name: string; Value: obj }

[<System.STAThread>]
do
  let column header binding =
    let binding = Data.Binding binding
    Controls.GridViewColumn(Header=header, DisplayMemberBinding=binding)

  for header, binding in ["Name", "Name"; "Value", "Value"] do
    column header binding
    |> gridView.Columns.Add

  for prop in typeof<SystemParameters>.GetProperties() do
    if prop.PropertyType <> typeof<ResourceKey> then
      { Name = prop.Name; Value = prop.GetValue(null, null) }
      |> listView.Items.Add
      |> ignore

  Application().Run(Window(Content=listView)) |> ignore

是的,这是可能的,但有点棘手,但一旦你掌握了方法,它就相当灵活了。WFP有一个灵活的模板系统,它可以通过代码和XAML实现,除了在代码中实现这一点的例子要少得多

它主要涉及如何使用
FrameworkElementFactory
覆盖列表框默认模板并显示所需的UI元素。然后使用
Binding
类指定控件应如何绑定到数据

我用WPF和F#编写了一个twitter客户端,并使用这种方法在列表框中显示tweet的列。看看
createTweetContainerTemplate
函数是如何工作的。


然后,除非您真的需要对列表框中的每一行的布局进行高度控制,否则使用datagrid可能更简单。

我制作了一个简单的combinator库来通过代码构建WPF UI,我在我的pit项目中使用此模式来创建HTML元素

命名空间FSharp.WPF 开放系统 开放系统 打开System.Windows.Controls

[<AutoOpen>]
module Combinator =
    type XDef =
    | Attr      of string * obj
    | Tag       of Type * XDef list
    //| Element   of FrameworkElement

    [<AutoOpen>]
    module Operators =
        let (@=) (p:string) (v:obj) : XDef = Attr(p,v)

    module internal Helpers =
        let createEl (ty:Type) = new FrameworkElementFactory(ty)

    let tag name attr   = Tag(name,attr)
    //let el dom          = Element(dom)

    let rec build (tag:XDef) =
        match tag with
        | Tag(ty,defs)    ->
            let attrs = defs |> List.choose(fun t -> match t with | Attr(k,v) -> Some(k,v) | _ -> None)
            let tags = defs |> List.choose(fun t -> match t with | Tag(k,v) -> Some(t) | _ -> None)
            /// create the element and set attributes
            let el = Helpers.createEl(ty)
            let rec setProps (d:(string*obj) list) =
                match d with
                | []     -> ()
                | (p,v) :: t ->
                    let dp = System.ComponentModel.DependencyPropertyDescriptor.FromName(p, el.Type,el.Type)
                    el.SetValue(dp.DependencyProperty,v)
            setProps attrs

            let rec gen (d:XDef list) =
                match d with
                | []    -> ()
                | h::t  ->
                    let childEl = build(h)
                    el.AppendChild(childEl)
                    gen(t)
            gen tags
            el
        //| Element(el)       -> el
        | Attr(key,value)   -> failwith "Unrecognized sequence"

    let make xdef =
        let fEl = build xdef
        let contentEl = new ContentControl()
        contentEl.ContentTemplate <- new DataTemplate(VisualTree=fEl)
        contentEl :> FrameworkElement
    let create() =
        tag typeof<System.Windows.Controls.Button> ["Content"@="Hello World"]
        |> Combinator.make

    let create2() =
        tag typeof<StackPanel> [
            tag typeof<Button> ["Content"@="Button 1"]
            tag typeof<Button> ["Content"@="Button 2"]
        ]
        |> Combinator.make

[<STAThread>]
[<EntryPoint>]
let main(_) =
    let el     = Test.create2() // Test.create1()
    let window = new Window(Content = el, Height = 600.0, Width = 800.0, Title = "WpfApplication1")
    let app = new Application()
    app.Run(window)
[]
模组合器=
XDef型=
|字符串*对象的属性
|类型为*XDef列表的标记
//|框架元素
[]
模运算符=
let(@=)(p:string)(v:obj):XDef=Attr(p,v)
模块内部助理=
让createEl(ty:Type)=新FrameworkElementFactory(ty)
让标记名attr=tag(名称,attr)
//设el dom=元素(dom)
让rec生成(标记:XDef)=
匹配标签
|标签(ty,defs)->
让attrs=defs |>列表。选择(乐趣t->将t与| Attr(k,v)->一些(k,v)|->无)
让tags=defs |>列表。选择(乐趣t->将t与| Tag(k,v)->一些(t)|->无)
///创建元素并设置属性
let el=Helpers.createEl(ty)
let rec setProps(d:(字符串*obj)列表)=
匹配
| []     -> ()
|(p,v)::t->
设dp=System.ComponentModel.DependencyPropertyDescriptor.FromName(p,el.Type,el.Type)
el.设定值(dp.DependencyProperty,v)
setProps属性
let rec gen(d:XDef列表)=
匹配
| []    -> ()
|h::t->
let childEl=构建(h)
el.AppendChild(儿童)
总务(t)
gen标签
埃尔
//|元素(el)->el
|Attr(键,值)->故障与“无法识别的序列”
让我们制作xdef=
设fEl=buildxdef
让contentEl=newcontentcontrol()
contentEl.ContentTemplate框架元素
它现在非常低调,只需要创建对象,但它可以扩展到更多的数据绑定和其他事情,并且一些类型检查应该可以发现对象创建中的错误

用法: 模块测试= 打开System.Windows.Controls

[<AutoOpen>]
module Combinator =
    type XDef =
    | Attr      of string * obj
    | Tag       of Type * XDef list
    //| Element   of FrameworkElement

    [<AutoOpen>]
    module Operators =
        let (@=) (p:string) (v:obj) : XDef = Attr(p,v)

    module internal Helpers =
        let createEl (ty:Type) = new FrameworkElementFactory(ty)

    let tag name attr   = Tag(name,attr)
    //let el dom          = Element(dom)

    let rec build (tag:XDef) =
        match tag with
        | Tag(ty,defs)    ->
            let attrs = defs |> List.choose(fun t -> match t with | Attr(k,v) -> Some(k,v) | _ -> None)
            let tags = defs |> List.choose(fun t -> match t with | Tag(k,v) -> Some(t) | _ -> None)
            /// create the element and set attributes
            let el = Helpers.createEl(ty)
            let rec setProps (d:(string*obj) list) =
                match d with
                | []     -> ()
                | (p,v) :: t ->
                    let dp = System.ComponentModel.DependencyPropertyDescriptor.FromName(p, el.Type,el.Type)
                    el.SetValue(dp.DependencyProperty,v)
            setProps attrs

            let rec gen (d:XDef list) =
                match d with
                | []    -> ()
                | h::t  ->
                    let childEl = build(h)
                    el.AppendChild(childEl)
                    gen(t)
            gen tags
            el
        //| Element(el)       -> el
        | Attr(key,value)   -> failwith "Unrecognized sequence"

    let make xdef =
        let fEl = build xdef
        let contentEl = new ContentControl()
        contentEl.ContentTemplate <- new DataTemplate(VisualTree=fEl)
        contentEl :> FrameworkElement
    let create() =
        tag typeof<System.Windows.Controls.Button> ["Content"@="Hello World"]
        |> Combinator.make

    let create2() =
        tag typeof<StackPanel> [
            tag typeof<Button> ["Content"@="Button 1"]
            tag typeof<Button> ["Content"@="Button 2"]
        ]
        |> Combinator.make

[<STAThread>]
[<EntryPoint>]
let main(_) =
    let el     = Test.create2() // Test.create1()
    let window = new Window(Content = el, Height = 600.0, Width = 800.0, Title = "WpfApplication1")
    let app = new Application()
    app.Run(window)
let create()=
标签类型[“Content”@=“Hello World”]
|>组合器
让我们创建2()=
标签类型[
标签类型[“内容”@=“按钮1”]
标签类型[“内容”@=“按钮2”]
]
|>组合器
[]
[]
let main(u)=
设el=Test.create2()//Test.create1()
let window=新窗口(内容=el,高度=600.0,宽度=800.0,Title=“WpfApplication1”)
let app=新应用程序()
应用程序运行(窗口)
正如您所看到的,嵌套元素意味着面板元素,但可能有一些额外的杠杆作用,允许类型识别面板元素或内容元素。但你知道,这可能是有用的。你觉得怎么样


-Fahad

通过使用基于索引的绑定而不是成员名,可以避免复制字段名的特定问题。请参见此处对示例所做的更改:

开放系统
开放系统
让gridView=Controls.gridView()
让listView=Controls.listView(View=gridView)
[]
做
让列索引标题=
let binding=Data.binding(sprintf“[%d]”索引)
Controls.GridViewColumn(标题=标题,DisplayMemberBinding=绑定)
[“名称”;“值”]
|>List.mapi列
|>List.iter gridView.Columns.Add
对于typeof.GetProperties()中的prop
如果prop.PropertyType类型为,则
([| prop.Name;prop.GetValue(null,null)|]:对象数组)
|>listView.Items.Add
|>忽略
Application().Run(Window(Content=listView))|>ignore
关于为
ListView
提供一系列控件,其级别略低于
ListView
ListView
DataGrid
都假设您有一些大致相同的对象集合,希望显示这些对象(通常为行),并且对这些对象的信息(列定义)有一些概念。这两个控件在这种情况下都会有所帮助,尽管我同意它们的一般假设,即您希望对类型的成员使用反射,这可能会很烦人

如果您希望能够指定任何控件的网格,那么正如您所提到的,
网格
面板布局可能更合适。

您还说了