同步命令与异步方法相反

问题描述 投票:0回答:1

我用Xamarin.Forms和sqlite-net-pcl Nuget包构建了一个非常简单的列表制作应用程序。我有一个模型,ListItem,具有布尔属性Active。有两个列表:activeItemsActive = trueinactiveItemsActive = 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中定义的方法,定义为“App.ListItemRepo”)

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");
        }
    }
}
c# sqlite asynchronous xamarin xamarin.forms
1个回答
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;
        });

我希望它有所帮助!如果没有,请告诉我:)

© www.soinside.com 2019 - 2024. All rights reserved.