我可以连接到数据库,并通过断点可以查看任务调用中返回的数据。在我的 Chambers.xaml.cs 文件中,当尝试在 Foreach 例程中使用它来填充 ListView 的绑定变量时,我在该任务的 listchamber 上收到 GetEnumerator 错误。
Chamber.xaml
```
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MrDiver.Views.Chambers"
Title="Chambers"
xmlns:models="clr-namespace:MrDiver.Models"
BackgroundColor="LightYellow"
>
<VerticalStackLayout
Spacing="30"
HorizontalOptions="Center"
BackgroundColor="LightGrey"
>
<Label Text="DCI EMERGENCY England, Northern Ireland or Wales phone 07831 151523" ></Label>
<Label Text="DCI EMERGENCY Scotland phone 0345 408 6008 " ></Label>
<ListView ItemsSource="{Binding ListChambers}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Model_Chambers">
<StackLayout>
<Label Text="{Binding Name}"/>
<Label Text="{Binding Town}"/>
<Label Text="{Binding Address}"/>
</StackLayout>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</VerticalStackLayout>
</ContentPage>
```
Chamber.xaml.cs
```
using MrDiver.Data;
using MrDiver.Models;
using System.Collections.ObjectModel;
namespace MrDiver.Views;
public partial class Chambers : ContentPage
{
public ObservableCollection<Model_Chambers> ListChambers { get; set; } = new();
public Chambers()
{
InitializeComponent();
PortDatabase portDatabase = new PortDatabase();
var listChambers = portDatabase.ChamberList();
ListChambers.Clear();
foreach (var model_Chambers in listChambers)
{
ListChambers.Add(model_Chambers);
}
}
}
```
PortDatabase.cs
```
using SQLite;
using MrDiver.Models;
namespace MrDiver.Data
{
public class PortDatabase
{
private readonly SQLiteAsyncConnection _database;
public static string DBPath { get; } =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Port.db3");
public PortDatabase()
{
// _database is the connection to read the database
_database = new SQLiteAsyncConnection(DBPath, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.SharedCache);
// creates a new table named Coastguard if it doesn't exist
_database.CreateTableAsync<Model_Chambers>();
}
public async Task<List<Model_Chambers>> ChamberList()
{
var cham = await _database.Table<Model_Chambers>().ToListAsync();
return cham;
}
}
}
```
Model_Chambers.cs
using SQLite;
namespace MrDiver.Models
{
[Table("ChambersTable")]
public class Model_Chambers
{
[PrimaryKey, AutoIncrement]
[Column("KEY")]
public int Key { get; set; }
[Column("NAME")]
public string? Name { get; set; }
[Column("ADDRESS")]
public string? Address { get; set; }
[Column("TOWN")]
public string? Town { get; set; }
[Column("COUNTY")]
public string? County { get; set; }
[Column("NATION")]
public string? Nation { get; set; }
[Column("TELEPHONE")]
public string? Telephone { get; set; }
}
}
我尝试了在线示例的各种变体,包括而不是简单地使用 Task 列表,但得到了无法转换显式 Typeof 错误。
listChambers
是Task<List<Model_Chambers>>
。任务是将来具有值的事物的表示,因此您需要等到该值可用才能对其进行迭代。有几种替代方法可以做到这一点:
.ToListAsync()
更改为 .ToList()
,并调整返回类型以匹配。portDatabase.ChamberList().Result
。这在功能上应该与选项 1 相同,但使用 .Result
是不受欢迎的,因为存在死锁的风险。我认为这些风险不适用于这种特定情况,但需要注意。var listChambers = await portDatabase.ChamberList()
。这需要您的方法被标记为异步。由于构造函数无法标记为异步,因此您需要将代码移至常规方法。您还需要考虑如何处理异常,以及填充列表可能需要一些时间。因此,请使用 try/catch,并考虑在实际数据到达后隐藏“正在加载...”标签。如果性能不是问题,我会选择选项 1,因为它很简单。如果数据库调用花费明显的时间,选项 3 可能是首选。