我使用Xamarin.Forms和sqlite-net-pcl Nuget包构建了一个非常简单的列表制作应用程序。我有一个模型ListItem
,其布尔属性为Active
。有两个列表:activeItems
,其中Active = true
和inactiveItems
,其中Active = false
。当用户点击activeItems
列表中的项目时,它将设置为Active = false
,并重新加载这两个列表。当用户点击inactiveItems
列表中的项目时,它将设置为Active = true
,并重新加载这两个列表。这一切都很有效。
但是,我还想提供永久删除项目的选项,而不仅仅是将其标记为完整。当用户长按一个项MenuItem
(在任一列表中)并选择"删除"时,ListItem将按预期从数据库中删除,但它不是从activeItems
列表中删除,inactiveItems
列表完全消失(当我重新加载页面时,inactiveItems
列表又回来了,activeItems
列表缺少已删除的项目,如预期的那样)。这真的很奇怪,因为我实际上是复制并粘贴了我的" SetActive / Inactive"方法进入我的" DeleteListItem"方法。唯一的区别是" DeleteListItem"是同步的,但我不明白为什么要让它做它正在做的事情。
旁注:对于每种方法,我重新加载两个列表中的HeightRequest
,因此它们完全符合其内容。
有人看到了这个问题吗?或者,如果有人知道如何制作我的" DeleteListItem"方法是异步的,这也是很好的,因为这个问题很可能发生。
更新
我尝试制作我的" DeleteListItem"异步,但行为没有改变。我还尝试使用App.ListItemRepo.GetActiveListItemsAsync());
代替App.ListItemRepo.GetActiveListItems());
,因为这是有效方法中使用的方法。但后来我得到了这个错误:
Error CS1503
Argument 1: cannot convert from 'System.Threading.Tasks.Task<System.Collections.Generic.List<Myapp.Models.ListItem>>' to 'System.Collections.Generic.List<Myapp.Models.ListItem>'
的Xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="..."
xmlns:x="..."
x:Class="Myapp.ListPage"
x:Name="ListPage">
<ScrollView Orientation="Vertical">
<StackLayout>
<!-- CURRENT ITEMS LIST -->
<StackLayout VerticalOptions="Fill" Orientation="Vertical" HorizontalOptions="StartAndExpand">
<ListView x:Name="activeList" VerticalOptions="Start" ItemTapped="SetInactive">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}">
<TextCell.ContextActions>
<MenuItem Command="{Binding Source={x:Reference ListPage}, Path=DeleteListItem}"
CommandParameter="{Binding .}" Text="delete" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
<!-- PAST ITEMS LIST -->
<ListView x:Name="inactiveList" VerticalOptions="Start" ItemTapped="SetActive" >
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}">
<TextCell.ContextActions>
<MenuItem Command="{Binding Source={x:Reference ListPage}, Path=DeleteListItem}"
CommandParameter="{Binding .}" Text="delete" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ScrollView>
</ContentPage>
代码隐藏:(使用ListItemRepository.cs中定义的方法,定义为&#34; App.ListItemRepo&#34;)
using Myapp.Models;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using SQLite;
using System.Threading.Tasks;
using System.IO;
using Xamarin.Forms;
using System.Diagnostics;
namespace Myapp
{
public partial class ListPage
{
public Command DeleteListItem { get; set; }
public ListPage()
{
InitializeComponent();
ObservableCollection<ListItem> activeItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetActiveListItems());
activeList.ItemsSource = activeItems;
activeList.HeightRequest = 50 * activeItems.Count;
ObservableCollection<ListItem> inactiveItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetInactiveListItems());
inactiveList.ItemsSource = inactiveItems;
inactiveList.HeightRequest = 50 * inactiveItems.Count;
});
// DELETE METHOD
DeleteListItem = new Command((parameter) => {
ListItem item = (ListItem)parameter as ListItem;
App.ListItemRepo.DeleteListItemAsync(item);
ObservableCollection<ListItem> commandActiveItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetActiveListItems());
activeList.ItemsSource = commandActiveItems;
activeList.HeightRequest = 50 * commandActiveItems.Count;
ObservableCollection<ListItem> commandInactiveItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetInactiveListItems());
inactiveList.ItemsSource = commandInactiveItems;
inactiveList.HeightRequest = 50 * commandInactiveItems.Count;
});
}
// SET AS ACTIVE METHOD
public async void SetActive(object sender, ItemTappedEventArgs e)
{
var selectedListItem = e.Item as ListItem;
await App.ListItemRepo.SetListItemActive(selectedListItem);
ObservableCollection<ListItem> activeItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetActiveListItemsAsync());
activeList.ItemsSource = activeItems;
activeList.HeightRequest = 50 * activeItems.Count;
ObservableCollection<ListItem> inactiveItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetInactiveListItemsAsync());
inactiveList.ItemsSource = inactiveItems;
inactiveList.HeightRequest = 50 * inactiveItems.Count;
}
// SET AS INACTIVE METHOD
public async void SetInactive(object sender, ItemTappedEventArgs e)
{
var selectedListItem = e.Item as ListItem;
await App.ListItemRepo.SetListItemInactive(selectedListItem);
ObservableCollection<ListItem> activeItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetActiveListItemsAsync());
activeList.ItemsSource = activeItems;
activeList.HeightRequest = 50 * activeItems.Count;
ObservableCollection<ListItem> inactiveItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetInactiveListItemsAsync());
inactiveList.ItemsSource = inactiveItems;
inactiveList.HeightRequest = 50 * inactiveItems.Count;
}
}
}
资产/ ListItemRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Myapp.Models;
using SQLite;
using System.Threading.Tasks;
namespace Myapp
{
public class ListItemRepository
{
private readonly SQLiteAsyncConnection conn;
private readonly SQLiteConnection syncconn;
public ListItemRepository(string dbPath)
{
conn = new SQLiteAsyncConnection(dbPath);
conn.CreateTableAsync<ListItem>().Wait();
syncconn = new SQLiteConnection(dbPath);
syncconn.CreateTable<ListItem>();
}
public async Task SetListItemActive(ListItem listItem)
{
ListItem item = (ListItem)listItem as ListItem;
var result = await conn.UpdateAsync(new ListItem { Id = item.Id, Active = true, Name = item.Name }).ConfigureAwait(continueOnCapturedContext: false);
}
public async Task SetListItemInactive(ListItem listItem)
{
ListItem item = (ListItem)listItem as ListItem;
var result = await conn.UpdateAsync(new ListItem { Id = item.Id, Active = false, Name = item.Name }).ConfigureAwait(continueOnCapturedContext: false);
}
public async Task DeleteListItemAsync(ListItem listItem)
{
ListItem item = (ListItem)listItem as ListItem;
var result = await conn.DeleteAsync(new ListItem { Id = item.Id }).ConfigureAwait(continueOnCapturedContext: false);
}
public Task<List<ListItem>> GetActiveListItemsAsync()
{
return conn.QueryAsync<ListItem>("select * from list_items where Active = 1");
}
public Task<List<ListItem>> GetInactiveListItemsAsync()
{
return conn.QueryAsync<ListItem>("select * from list_items where Active = 0");
}
public List<ListItem> GetActiveListItems()
{
return syncconn.Query<ListItem>("select * from list_items where Active = 1");
}
public List<ListItem> GetInactiveListItems()
{
return syncconn.Query<ListItem>("select * from list_items where Active = 0");
}
}
}
答案 0 :(得分:1)
您可以异步调用命令。只需在DeleteListItem命令中添加async关键字(参数)即可。然后,您还应该异步调用DeleteListItemAsync方法。最后,调用GetActiveListItemsAsync而不是GetActiveListItemsAsync。
DeleteListItem = new Command(async (parameter) => {
ListItem item = (ListItem)parameter as ListItem;
await App.ListItemRepo.DeleteListItemAsync(item);
ObservableCollection<ListItem> commandActiveItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetActiveListItemsAsync());
activeList.ItemsSource = commandActiveItems;
activeList.HeightRequest = 50 * commandActiveItems.Count;
ObservableCollection<ListItem> commandInactiveItems =
new ObservableCollection<ListItem>(
await App.ListItemRepo.GetInactiveListItemsAsync());
inactiveList.ItemsSource = commandInactiveItems;
inactiveList.HeightRequest = 50 * commandInactiveItems.Count;
});
我希望它有所帮助!如果没有,请告诉我:)。