codejourney
codejourney

Reputation: 319

How to delete items from a collection view in xamarin.forms?

NOTE: this didn't work : SQLite Error: Cannot delete WhereListIterator`1: it has no PK (Adding a table name made no change)

I have an AcceuilPage which basically do this : https://github.com/devcrux/Xamarin.Forms-Expander but i added a delete icon and when i press it i want to be able to delete all the content for this date ( also the date) from this page.

So i added a delete function to delete it from database but when i expand for a date and press delete i get this error : Exception: System.NotSupportedException: Cannot delete Object: it has no PK which bring me to await App.Database.DeleteAgendaAsync(agenda); in :

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

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

}

i also tried for the error line this : await App.Database.DeleteAgendaAsync(agenda); but this didn't even do anything when i pressed it ( no error and nothing happening).

I saw that this was a working fine for a listview but im struggling to do it in a collectionview, feels to me like it doesn't know if i am currently selecting something. ( With listview, when u click an item, the item view change color).

What am i doing wrong, im also starting to think that using a listview would be more simple.

My 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>

My 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; }

    }
}

Upvotes: 1

Views: 3777

Answers (1)

ColeX
ColeX

Reputation: 14475

When we touch on the imagebutton/button , the click event triggers , but it does not mean we select an item in CollectionView ,the button click event covers the click/tap event on item of Collectionview itself, so in this scenario , AgendaCollection.SelectedItem is null ,then the error happens .

For the second approach you used: var agenda = (Agenda)BindingContext; , you set BindingContext in constructor : BindingContext = new Agenda(); , BindingContext is a brand new object which is not the one you are selecting .

To solve the prorblem , you could get the imagebutton's BindingContext and then manipulate the logic .

 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();

    }

Update

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

        return result;
    }

Upvotes: 4

Related Questions