Xamarin.Formsとsqlite-net-pcl Nugetパッケージを使用して非常に単純なリスト作成アプリケーションを作成しました。私は単一のモデルListItem
を持っていて、ブール値の属性はActive
です。 2つのリスト:activeItems
、Active = true
、およびinactiveItems
(Active = false
)。ユーザがactiveItems
リスト内の項目をタップすると、Active = false
に設定され、2つのリストがリロードされます。ユーザーがinactiveItems
リスト内の項目をタップすると、Active = true
に設定され、2つのリストがリロードされます。すべてこれは素晴らしい作品です。同じ非同期メソッドとは逆の同期コマンド
しかし、完全なものとしてマークするだけでなく、アイテムを完全に削除するオプションも提供したいと考えています。ユーザーがアイテムのMenuItem
(いずれかのリストにある)を長時間保持して「削除」を選択すると、ListItemはデータベースから削除されますが、activeItems
リストから削除されず、inactiveItems
リストは完全に消滅しますページをリロードすると、inactiveItems
の一覧が戻って、activeItems
の一覧には、削除された項目が不足しています)。これは文字通り私の "SetActive/Inactive"メソッドを "DeleteListItem"メソッドにコピー&ペーストしたので、これは本当に奇妙です。唯一の違いは、 "DeleteListItem"は同期的ですが、なぜそれがそれが何をしているのかを理解する必要はありません。
サイドノート:それぞれの方法について、私は両方のリストのHeightRequest
をリロードして、内容に正確に合致します。
誰でも問題を確認できますか?または、誰かが私の "DeleteListItem"メソッドを非同期にする方法を知っていれば、それは問題であるという機会に、素晴らしいことかもしれません。
更新
私は私の "DeleteListItem" 非同期を作ってみましたが、動作は変更されませんでした。私はApp.ListItemRepo.GetActiveListItems());
の代わりにApp.ListItemRepo.GetActiveListItemsAsync());
を使用しようとしました。これは動作するメソッドで使用されているメソッドなのでです。しかし、私はこのエラーを取得する:
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>
コードビハインド:( "App.ListItemRepo" と定義し、ListItemRepository.csで定義されたメソッドを使用しています)
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");
}
}
}
ありがとう!しかし、その行動は変わらなかった。これはとても奇妙です。私は 'App.ListItemRepo.GetActiveListItems'を' App.ListItemRepo 'に変更しようとしました。GetActiveListItemsAsync'は動作するメソッドで使用されているメソッドですが、このエラーが発生します: '引数1: 'System.Threading.Tasks.Task> 'を' System.Collections.Generic.List 'に設定します。私はそれをどのように救うことができるか知っていますか? –
あなたはその電話を待っていますか? – Jason
Jasonが示唆するように、このメソッドの呼び出しを待つ必要があります。 – Kuba