Forum Xamarin.Forms

how to delete an item in a ListView using SwipeView

jddjdd USMember ✭✭✭

Hi, this seems to be easy but not for everyone.

I can delete the item using Command (the right way for MVVM) or using code behind.

First, if I use code behind it is easy to display an alert message but I don't know how to get the item:
XAML:

                                   <SwipeItems Mode="Execute">
                                        <SwipeItem Text="{i18n:Translate buttonDelete}"
                                                IconImageSource="delete.png"
                                                BackgroundColor="{StaticResource TextRedNightColor}"
                                                Invoked="OnDelete"/>
                                    </SwipeItems>

code behind:

        async void OnDelete(object sender, EventArgs args)
        {
                bool answer = await DisplayAlert(
                rm.GetString("warning"),
                rm.GetString("messageDeleteSight"),
                rm.GetString("deleteAnyway"),
                rm.GetString("cancel"));
                if (answer)
                {
                    //await AlmicantaratXF.Views.App.PositionsSightsDB.DeleteSightAsync(***some thing to write here to get the item***);
                }
            }
        }

When I tap on an item I get the item easily:

        async void OnSightSelected(object sender, SelectedItemChangedEventArgs e)
        {
            (sender as ListView).SelectedItem = null;
            if (e.SelectedItem != null)
            {
                await Navigation.PushAsync(new SightPage(e.SelectedItem as Sight));
            }
        }

But when I swipe the item I don't have any SelectedItemChangedEventArgs e, so I don't know how to get the item.

Second, I did delete the item using Command, but there is no more alert message and I don't know how to refresh the ListView so that the item does not appear anymore.
The ListView is populated during the OnAppearing (does that help?):

        protected override async void OnAppearing()
        {
            base.OnAppearing();
            Model.Position currentPosition = BindingContext as Model.Position;
            listView.ItemsSource = await AlmicantaratXF.Views.App.PositionsSightsDB.GetSightsAsync(currentPosition);
        }
  1. how to get the item in the code behind after a swipe?
  2. how to refresh the listview when the item is deleted?

Best Answer

Answers

  • jddjdd USMember ✭✭✭

    Thank you @LandLu
    My code below.
    Few remarks:
    1. I need to delete my item twice:

    • in the app database
    • in the observable collection
    1. from the beginning I use the the async methods of the sqlite-net-pcl NuGet package.
      It makes difficult to convert Task<List<T>> to Task<ObservableCollection<T>> so I go through .Result which makes async unuseful.
    2. I could use a private ObservableCollection<Sight> sightCollection in my code behind which would make the code cleaner.
    namespace AlmicantaratXF.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class CelestialPositionPage : ContentPage
        {
            private ResourceManager rm = Strings.ResourceManager;
            public CelestialPositionPage ()
            {
                InitializeComponent ();
            }
            protected override async void OnAppearing()
            {
                base.OnAppearing();
                Model.Position currentPosition = BindingContext as Model.Position;
                listView.ItemsSource = AlmicantaratXF.Views.App.PositionsSightsDB.GetSightsCollection(currentPosition);
            }
            async void OnDeleteSight(object sender, EventArgs args)
            {
                SwipeItem item = sender as SwipeItem;
                Sight sightToDelete = item.BindingContext as Sight;
                ObservableCollection<Sight> sightsCollection = listView.ItemsSource as ObservableCollection<Sight>;
                if (sightToDelete != null)
                {
                    bool answer = await DisplayAlert(
                    rm.GetString("warning"),
                    rm.GetString("messageDeleteSight"),
                    rm.GetString("deleteAnyway"),
                    rm.GetString("cancel"));
                    if (answer)
                    {
                        await AlmicantaratXF.Views.App.PositionsSightsDB.DeleteSightAsync(sightToDelete);
                        sightsCollection.Remove(sightToDelete);
                    }
                }
            }
        }
    }
    
  • LandLuLandLu Member, Xamarin Team Xamurai

    It makes difficult to convert Task<List> to Task<ObservableCollection>

    We could convert it easily like:

    List<T> list = new List<T>();
    ObservableCollection<T> collection = new ObservableCollection<T>(list);
    

    Try to retrieve it from sqlite database using list and convert it to ObservableCollection when applying it on listview.

Sign In or Register to comment.