7
votes

I'm trying to remove items/rows from a ListView but the difficulty is that I need to also pass in some delegate or fire some event or something, so when a person clicks a button to remove that row, my code handles some other logic, elsewhere (eg. remove the item from the DB or whatever).

I have a custom control I made:

public class SportsTeam : StackLayout { .. }

Inside this control, one of the elements is a ListView which lists all the people in a sporting team.

var viewModel = teamMembers.Select(x => new SportsTeamViewModel(x));

return new ListView
{
    HasUnevenRows = true,
    ItemSource = viewModel,
    ItemTemplate = new DataTemplate(typeof(SportsTeamViewCell)); 
};

Inside the SportsTeamViewCell I have the following:

private Grid CreateContent()
{
    var grid = new Grid();
    // Setup row and column definitions.
    // Add items to the Grid 
    grid.Children.Add(...);

    var removeButton = RemoveButton;
    grid.Children.Add(removeButton);
    Grid.SetRowSpan(removeButton, 2);

    return grid;
}

private Button RemoveButton
{
    get
    {
        var button = new Button
        {
            Image = "Icons/remove.png"
        };

        return button;
    }
}

From here, I don't know how to make it so that the button fires an event or some delete could be passed in via the constructor, so some custom logic is performed against the individual cell/row/item that is to be removed.

3
Pass the Id of the Row to be deleted into click event handler of the RemoveButton.Rohit Vipin Mathews
How do I find the Id of the row to be deleted? Or can each row have another special Id which I give it? like some hidden magical id? Or the value of something else from the bound data? eg. the Id or UserName or whatever ....Pure.Krome
Yes, you have to use the Bindings and bind your model's Id property to click event of button.Rohit Vipin Mathews

3 Answers

9
votes

Here is what you could do :

This be my model class :

public class Item  
{  
   public string ItemName { get; set; }  
   public string ItemDetails { get; set; }  
}  

And in my XAML or you can write this in code as well, bind to the Command Parameter of your Item template :

<Button Text="Delete" CommandParameter="{Binding ItemName}" Clicked="DeleteClicked"></Button>

Full Item Template will be like below :

<ListView.ItemTemplate>  
            <DataTemplate>  
               <ViewCell>  
                  <ViewCell.View>  
                     <StackLayout Orientation="Horizontal">  
                        <Label Text="{Binding ItemName}" HorizontalOptions="StartAndExpand" FontSize="30"></Label>  
                        <Button Text="Delete" CommandParameter="{Binding ItemName}" Clicked="DeleteClicked">        
                        </Button>  
                     </StackLayout>  
                  </ViewCell.View>  
               </ViewCell>  
            </DataTemplate>  
         </ListView.ItemTemplate>    

And in you code file you can do this :

public void DeleteClicked(object sender, EventArgs e)  
{  
   var item = (Xamarin.Forms.Button)sender;  
   Item listitem = (from itm in allItems 
                    where itm.ItemName == item.CommandParameter.ToString() 
                    select itm)
                   .FirstOrDefault<Item>();  
   allItems.Remove(listitem);  
}  

IMPORTANT : This would only delete the item from the bound collection. To delete it from the original list you need to use ObservableCollection

Here is the full source code of the explained scenario - Handling Child Control Event in Listview using XAMARIN.FORMS.

Also the Tutorial - How to handle Row selection and delete Button in Row For Custom ListView using Xamarin.Forms explain deletion from a listview as well.

2
votes

I've found a similar approach and I want to share it. I filled the list with an ObservableCollection<MyObject>. Then I filled the CommandParameter with just CommandParameter="{Binding .}". So I got the whole Object back. Then you can just cast the CommandParameterto your Object and remove it from the ObservableCollection<MyObject> List

XAML:

CommandParameter="{Binding .}"

Filling my List:

savingExpensesCollection = new ObservableCollection<SavingsExpensesEntry> ();
savingExpensesCollection .Add (new SavingsExpensesEntry ("1000 mAh Akku", "Dampfgarten", new DateTime (635808692400000000), 8.95));
savingExpensesCollection .Add (new SavingsExpensesEntry ("Cool-Mint Aroma", "Dampfgarten", new DateTime (635808692400000000), 3.95));
savingExpensesCollection .Add (new SavingsExpensesEntry ("Basis", "Dampfgarten", new DateTime (635808692400000000), 13.65));

savingExpensesList.ItemsSource = savingExpenses;

EventHandler:

void OnDelete(object sender, EventArgs e)
{
    var menuItem = ((MenuItem)sender);
    SavingsExpensesEntry see ((SavingsExpensesEntry)menuItem.CommandParameter);
    savingExpensesCollection .Remove (see);
}

I've using a MenuItem but it's the same approach with a Button

-1
votes

I just did using delete button

  public void OnDelete(object sender, EventArgs e)
    {
        var mi = ((MenuItem)sender);

        PhotoViewModel photo= ((photoViewModel)mi.CommandParameter);
        photoModel.Remove(photo);
    }