【问题标题】:How to delete items from a collection view in xamarin.forms?如何从 xamarin.forms 的集合视图中删除项目?
【发布时间】:2020-06-26 13:24:48
【问题描述】:

注意:这不起作用:SQLite Error: Cannot delete WhereListIterator`1: it has no PK (添加表名没有改变)

我有一个 AcceuilPage,它基本上是这样做的:https://github.com/devcrux/Xamarin.Forms-Expander 但我添加了一个删除图标,当我按下它时,我希望能够从这个页面删除这个日期(也是日期)的所有内容。

所以我添加了一个删除功能以将其从数据库中删除,但是当我展开一个日期并按删除时,我收到此错误:异常: System.NotSupportedException:无法删除对象:它没有 PK 让我等待 App.Database.DeleteAgendaAsync(agenda);在:

async void DeleteButtonClicked(object sender, EventArgs e)
{
    
    var agenda = (Agenda)AgendaCollection.SelectedItem;

    await App.Database.DeleteAgendaAsync(agenda);
    await Navigation.PopAsync();

}

我也尝试了这个错误行:await App.Database.DeleteAgendaAsync(agenda);但是当我按下它时它甚至没有做任何事情(没有错误也没有发生任何事情)。

我看到这对于列表视图来说是一个很好的工作,但我在一个集合视图中努力做到这一点,对我来说感觉就像它不知道我当前是否正在选择某些东西。 (使用列表视图,当您单击一个项目时,项目视图会改变颜色)。

我做错了什么,我也开始认为使用列表视图会更简单。

我的 AcceuilPage.xaml

<ContentPage.Content>
            <!-- ScrollView nous permet d'avoir une page scrollable-->
     
                <ScrollView Orientation="Vertical">
                
                <CollectionView Grid.Row="2" Margin="25" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
                        SelectionMode="None"  x:Name="AgendaCollection"> <!--ItemsSource="{Binding AngedaCollection}" -->
                    <CollectionView.Header>
                        <StackLayout Orientation="Horizontal" Spacing="220">
                            <Label Text="Agenda" TextColor="Black" FontSize="18"/>
                            <StackLayout Orientation="Horizontal">
                                
                            
                                <ImageButton Source="iconplus.png"  HeightRequest="30" WidthRequest="30" Clicked="GoToNewFormPage"></ImageButton>
                                <ImageButton Source="iconmoins.png"  HeightRequest="30" WidthRequest="30"></ImageButton>
                            </StackLayout>


                        </StackLayout>
                        
                        

                    </CollectionView.Header>

                    <CollectionView.ItemsLayout>
                        <LinearItemsLayout Orientation="Vertical" ItemSpacing="20"/>
                    </CollectionView.ItemsLayout>
                    <CollectionView.ItemTemplate >
                        <DataTemplate>
                            
                                <pv:PancakeView HasShadow="True" BackgroundColor="White" VerticalOptions="StartAndExpand " 
                                    HorizontalOptions="FillAndExpand">
                                <Grid VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <BoxView BackgroundColor="{Binding Color}" WidthRequest="3" HorizontalOptions="Start"
                                     VerticalOptions="FillAndExpand"/>
                                    <Expander Grid.Column="1" >
                                        <Expander.Header>
                                            <Grid HorizontalOptions="FillAndExpand">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="3.5*"/>
                                                </Grid.ColumnDefinitions>
                                                <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
                                                    <Label Text="{Binding Date, StringFormat='{0:dd}'}" TextColor="#008A00" FontSize="27" 
                                                   HorizontalOptions="Center"/>

                                                    <Label Text="{Binding Date, StringFormat='{0:MMMM}'}" TextColor="Black" FontSize="10" 
                                                   HorizontalOptions="Center" Margin="0,-10,0,0" FontAttributes="Bold"/>
                                                    <ImageButton Source="iconplus.png" HorizontalOptions="Center" HeightRequest="30" WidthRequest="30" Clicked="GoToFormPage"></ImageButton>
                                                </StackLayout>
                                                <BoxView Grid.Column="1" BackgroundColor="#F2F4F8" WidthRequest="1" HorizontalOptions="Start" 
                                                 VerticalOptions="FillAndExpand"/>
                                                <StackLayout x:Name="topicLayout" Grid.Column="2" HorizontalOptions="Start" VerticalOptions="Center" Margin="20">
                                                    <Label Text="{Binding Topic}" TextColor="#008A00" FontSize="15" FontAttributes="Bold"/>
                                                    <Label Text="{Binding Duration}" TextColor="#2F3246" FontSize="12" Margin="0,-10,0,0"/>
                                                    <ImageButton Source="iconmoins.png"  HeightRequest="30" WidthRequest="30" Clicked="DeleteButtonClicked"></ImageButton>
                                                </StackLayout>
                                            </Grid>
                                        </Expander.Header>
                                        <Grid HorizontalOptions="FillAndExpand">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width="Auto"/>
                                                <ColumnDefinition Width="3.5*"/>
                                            </Grid.ColumnDefinitions>
                                            <BoxView Grid.Column="1" BackgroundColor="#F2F4F8" WidthRequest="1" HorizontalOptions="Start" 
                                             VerticalOptions="FillAndExpand"/>
                                            <StackLayout Grid.Column="2" Spacing="10">
                                                <Label Text="Tâches" TextColor="Black" FontSize="15" Margin="20,0"/>
                                                <StackLayout BindableLayout.ItemsSource="{Binding Speakers}" HorizontalOptions="Start" VerticalOptions="Center" Margin="20,0,0,20">
                                                    <BindableLayout.ItemTemplate>
                                                        <DataTemplate>
                                                            <Label TextColor="#2F3246" FontSize="12">
                                                                <Label.FormattedText>
                                                                    <FormattedString>
                                                                        <FormattedString.Spans>
                                                                            <Span Text="{Binding Time}"/>
                                                                            <Span Text=" - "/>
                                                                            <Span Text="{Binding Name}" FontAttributes="Bold"/>
                                                                        </FormattedString.Spans>
                                                                    </FormattedString>
                                                                </Label.FormattedText>
                                                            </Label>
                                                        </DataTemplate>
                                                        
                                                    </BindableLayout.ItemTemplate>
                                                    
                                                </StackLayout>

                                                
                                            </StackLayout>
                                        </Grid>
                                    </Expander>
                                </Grid>
                            </pv:PancakeView>
                            
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>



            </ScrollView>
              
        </ContentPage.Content>

我的 AcceuilPage.xaml.cs

using Calculette.ViewModel;
using Calculette.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.PancakeView;

namespace Calculette
{
    public partial class MainPage : TabbedPage
    {
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new Agenda();

        }
        protected async void GoToFormPage(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new Views.AgendaItemDetailPage());
        }
        protected async void GoToNewFormPage(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new Views.NewFormPage());
        }


        async void DeleteButtonClicked(object sender, EventArgs e)
        {
            
            var agenda = (Agenda)BindingContext;

            await App.Database.DeleteAgendaAsync(agenda);
            await Navigation.PopAsync();

        }

        protected override async void OnAppearing()
        {
           base.OnAppearing();
            AgendaCollection.ItemsSource = await App.Database.GetAgendasAsync();
        }
    }

}

AgendaDatabase.cs

using System;
using System.Collections.Generic;
using System.Text;
using SQLite;
using Calculette.Models;
using System.Threading.Tasks;

namespace Calculette.Database
{
    public class AgendaDatabase
    {
        readonly SQLiteAsyncConnection database;

        public AgendaDatabase(string dbPath)
        {
           
            database = new SQLiteAsyncConnection(dbPath);
            database.CreateTableAsync<Agenda>().Wait();
        


        }

        // Get all agenda
        public Task<List<Agenda>> GetAgendasAsync()
        {
            return database.Table<Agenda>().ToListAsync();
        }

        // Get specific agenda
        public Task<Agenda> GetAgendaAsync(int id)
        {
            return database.Table<Agenda>()
                            .Where(i => i.ID == id)
                            .FirstOrDefaultAsync();
        }

        // Insert new agenda (save)
        public Task<int> SaveAgendaAsync(Agenda agenda)
        {
            if (agenda.ID != 0)
            {
                return database.UpdateAsync(agenda);
            }
            else
            {
                return database.InsertAsync(agenda);
            }
        }
        
        //Delete specific agenda
        public Task<int> DeleteAgendaAsync(Agenda agenda)
        {
            return database.DeleteAsync(agenda);
        }
    }
}

Agenda.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using SQLite;
using Calculette.Database;

namespace Calculette.Models
{
    [Table("Agenda")]
    public class Agenda
    {
        [PrimaryKey, AutoIncrement]
        public int ID { get; set; }
        public string Topic { get; set; }
        public string Duration { get; set; }
        public DateTime Date { get; set; }

    }
}

【问题讨论】:

  • 嗨,是的,我读过它,唯一不同的是我没有添加的表名:[Table("Agenda")] 这没有解决,除非你在说话关于别的事情。谢谢。我添加了我的 Agenda.cs 文件

标签: sqlite xamarin xamarin.forms


【解决方案1】:

当我们点击 imagebutton/button 时,会触发 click 事件,但这并不意味着我们在 CollectionView 中选择了一个 item,button click 事件覆盖了 Collectionview 本身 ​​item 上的 click/tap 事件,所以在这种情况下, AgendaCollection.SelectedItem 为空,则发生错误。

对于您使用的第二种方法:var agenda = (Agenda)BindingContext;,您在构造函数中设置BindingContextBindingContext = new Agenda();BindingContext 是一个全新的对象,不是您选择的对象。

为了解决这个问题,你可以得到imagebutton's BindingContext然后操作逻辑。

 async void DeleteButtonClicked(object sender, EventArgs e)
    {
        
        ImageButton button = sender as ImageButton;
        var agenda = button.BindingContext as Agenda;

        await App.Database.DeleteAgendaAsync(agenda);
        await Navigation.PopAsync();

    }

更新

   public ObservableCollection<Agenda> GetAgendasAsync()
    {
        List<Agenda>list = database.Table<Agenda>().ToListAsync().Result;
        ObservableCollection<Agenda> result = new ObservableCollection<Agenda>(list);

        return result;
    }

【讨论】:

  • 您好,感谢您的回复,这对我很有帮助。我只有一个问题,当我删除某些东西时,我需要重新加载我的模拟器才能进行更改(要删除的已删除项目)。我知道我正在使用 await Navigation.PopAsync();因为我已经在我的主页上,所以没有任何方法可以在删除项目后动态重新加载页面?非常感谢 !或者当我实现 MVVM 风格并更改 inotifyproperty 时,这会得到解决吗? :)
  • 您需要将 ItemSource 从 List 更改为 ObservableCollection ,当数据更改时会自动通知更改并重新加载 UI。
  • 嗨,你是说这样做吗? : public Task> GetAgendasAsync() { return database.Table().ToListAsync();如果是,我应该更改返回 database.Table().ToListAsync();行,因为它说:不可能隐式转换类型?谢谢
  • 我不太确定我应该在哪里这样做?谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多