从视图函数创建 Xamarin.Forms.DataTemplate



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 中。这将是最安全、最简单的解决方案。

最新更新