CollectionView(或ListView)提供了一种查看对象序列(类型为T
)的方法。与 StackLayout 或 Grid 相比,它的优势在于视图仅在需要时加载。
为每个对象指定视图的自然方法是提供一个函数v:T->View
(F#)。
但是,CollectionView/ListView期望DataTemplate
。DataTemplate 类与绑定密切相关,因此 API 是不自然的、没有信息的和类型不安全的。有用的属性似乎与类型IDictionary<BindableProperty,Object>
Values
.
是否可以绕过此 API 并创建一个接受v:T->View
并返回DataTemplate
的函数?这将允许为DataTemplate创建一个干净的API,从而为ListView和CollectionView创建一个干净的API。
实现此目的的一种方法是创建自己的DataTemplate和ViewCell。
DataTemplate 只需要从 ViewCell 派生的类型,以便在列表视图需要时进行实例化。 然后,它调用此新创建/重用的 ViewCell 的OnBindingContextChanged
方法,并传递元素的相应值。
此时,您可以访问ViewCell.View
属性,该属性将包含要显示的控件。 您可以在此时执行您的函数。
在您的情况下,由于您有一个'T
列表 ,这将是这样的:
type FuncViewCell(createFunc: 'T -> View) =
inherit ViewCell()
override x.OnBindingContextChanged () =
let data = x.BindingContext :?> 'T
x.View <- createFunc data
type FuncDataTemplate(createFunc: 'T -> View) =
inherit DataTemplate(fun () -> FuncViewCell(createFunc))
(...)
let createViewForData data =
Button(Text = data.Text)
let listView = ListView()
listView.ItemTemplate <- FuncDataTemplate(createViewForData)
listView.ItemsSource <- dataSource
----
Or even directly:
type FuncListView(createFunc) =
inherit ListView(DataTemplate = FuncDataTemplate(createFunc))
let listView = FuncListView(createViewForData)
listView.ItemsSource <- dataSource
类似的方法可以在Fabulous.XamarinForms中找到。
不同之处在于该元素带有自己的视图创建功能。因此,无需扩展数据模板来传递函数。
https://github.com/fsprojects/Fabulous/blob/79c5df748fff7a108dfbcbf8609cb2265a8fddc7/Fabulous.XamarinForms/src/Fabulous.XamarinForms.Core/CustomControls.fs#L110-L151
解决方案是使用DataTemplateSelector。
这是这个的链接:-
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector
您可以做的是从 API 调用中获取数据模板 ID,并根据该 ID 选择该特定数据模板。您将制作许多数据模板并存储在页面的 Xaml 中。这将是最安全、最简单的解决方案。