MVVM ListView MenuItem ObservableCollection Delete Item

Deos69Deos69 Member ✭✭

Hi, I need to delete an item in my listview but it doesn't work
Here, xaml :

<ListView Grid.Row="4" Grid.ColumnSpan="3"
                ItemsSource="{Binding PaymentLines}"                               
                RowHeight="70" x:Name="items">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <ViewCell.ContextActions>
                                        <MenuItem  BindingContext="{Binding Source={x:Reference TicketRecapView}, Path=BindingContext}" Command="{Binding  DeleteCommand}" Text="Supprimer" IsDestructive="True" />
                                    </ViewCell.ContextActions>
                                    <Grid VerticalOptions="Center">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="*" />
                                        </Grid.ColumnDefinitions>                                       

                                        <Label Grid.Column="0"
                                       HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
                                       FontSize="13"
                                       Text="{Binding Name}" />
                                        <Label Grid.Column="2"
                                       HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
                                       FontSize="13"
                                       Text="{Binding Price}"  />
                                    </Grid>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>

Here my VM :
public PaymentConfirmationVM() {

    PaymentLines = new ObservableCollection<PaymentLigne>();

}

#region PaymentLines property
        ObservableCollection<PaymentLigne> _PaymentLines;

        public ObservableCollection<PaymentLigne> PaymentLines
        {
            get { return _PaymentLines; }
            set { SetProperty(ref _PaymentLines, value); }
        }
        #endregion

        #region Delete Command

        Command<PaymentLigne> _DeleteCommand;

        public Command<PaymentLigne> DeleteCommand
        {
            get { return GetProperty(ref _DeleteCommand, () => new Command<PaymentLigne>(Ligne => Delete(Ligne))); }
        }
        void Delete(PaymentLigne Ligne)
        {
            PaymentLines.Remove(Ligne);
        }

And here, my object observable :

public class PaymentLigne
    {
        public string Name { get; set; }
        public decimal Price { get; set; }

    }

I have an error when i put just a Command="{Binding DeleteCommand}" cause my object doesn't have the function DeleteCommand.
So i tried to put a reference for using the DeleteCommand in my VM. I don't know how to link, I think the problem is easy but I don't found a topic with MVVM.

Thx

Answers

  • GraverobberGraverobber Member ✭✭✭
    edited July 17

    Yes your problem is that you try to Bind the DeleteCommand in your MenuItem meanwhile the Command is defined in your ViewModel but the BindingContext of your MenuItem is not the ViewModel, it is the single PaymentLine.

    To solve that you need to tell the Binding where the Command is actually defined, something like this:

    Give your ContentPage a name
    <ContentPage x:Name="MyPage"....>

    In your MenuItem then do:
    Command="{Binding Path=BindingContext.DeleteCommand, Source={x:Reference MyPage}}"

    That should do the trick. It tells the Command of your MenuItem to use the property DeleteCommand of the BindingContext that is available under the source of MyPage.

  • Deos69Deos69 Member ✭✭
    edited July 17

    Hello,

    I Have already did that : my content page is "TicketRecapView".

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    x:Name="TicketRecapView"

    I have already did BindingContext.DeleteCommand but nothing... :( I have no error nothing.

    Here my xaml with your correction :

     <StackLayout VerticalOptions="FillAndExpand" >
    
        <v:CustomerHeaderView BindingContext="{Binding Header}"/>
    
        <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="Center" Padding="10">
    
          <StackLayout VerticalOptions="StartAndExpand" Spacing="15" >
            <StackLayout Orientation="Horizontal" Spacing="2">
              <Label Text="Règlement de" FontSize="22" />
              <Label Text="{Binding TotalPanier}" FontSize="22" />
              <Label Text="article(s)" FontSize="22" />
            </StackLayout>     
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50" />
                            <RowDefinition Height="40" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="50" />
                            <RowDefinition Height="350" />
                            <RowDefinition Height="100" />                      
                        </Grid.RowDefinitions>
                        <Label Grid.Row="0" Grid.Column="0" HorizontalOptions="End" VerticalOptions="Center" Text="Total TTC : "  StyleClass="FormLabel"/>
                        <Label Grid.Row="0" Grid.Column="1" HorizontalOptions="EndAndExpand"  Text="{Binding TTC, Converter={StaticResource DecimalToPriceConverter}, ConverterParameter=currency}" FontSize="30" />
                        <Label Grid.Row="1" Grid.Column="0" HorizontalOptions="End" VerticalOptions="Center" Text="Reste : "   StyleClass="FormLabel"/>
                        <Label Grid.Row="1" Grid.Column="1" HorizontalOptions="EndAndExpand" Text="{Binding ResteAPayer, Converter={StaticResource DecimalToPriceConverter}, ConverterParameter=currency}"   FontSize="25"/>
    
    
                        <Entry Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"  Text="{Binding PrixSaisie, Converter={StaticResource DecimalToTextConverter}}" Keyboard="Numeric"/>
    
                        <ListView Grid.Row="4" Grid.ColumnSpan="3"
                    ItemsSource="{Binding PaymentLines}"                               
                    RowHeight="70" x:Name="items">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <ViewCell>
                                        <ViewCell.ContextActions>
                                            <MenuItem  Command="{Binding Path=BindingContext.DeleteCommand, Source={x:Reference TicketRecapView}}" Text="Supprimer" IsDestructive="True" />
                                        </ViewCell.ContextActions>
                                        <Grid VerticalOptions="Center">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*" />
                                                <ColumnDefinition Width="*" />
                                            </Grid.ColumnDefinitions>                                       
    
                                            <Label Grid.Column="0" Grid.ColumnSpan="2"
                                           HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand"
                                           FontSize="13"
                                           Text="{Binding Name}" />
                                            <Label Grid.Column="2"
                                           HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand"
                                           FontSize="13"
                                           Text="{Binding Price, Converter={StaticResource DecimalToPriceConverter}, ConverterParameter=currency}"  />
                                        </Grid>
                                    </ViewCell>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
    
                        <Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="3"  VerticalOptions="Center">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="*" />
                                                    <RowDefinition Height="*" />
                                                </Grid.RowDefinitions>
    
                                  <Button Grid.Row="0"  Grid.Column="0" Text="&#xf2c2; Cheque"   Command="{Binding AddCommandCheque}" FontFamily="FontAwesome"  StyleClass="Secondary"  HeightRequest="100"
                                                WidthRequest="5"  />
                            <Button Grid.Row="0" Grid.Column="1" Text="&#xf09d; Carte" Command="{Binding AddCommandCarte}" FontFamily="FontAwesome"  StyleClass="Secondary" HeightRequest="100" />
                            <Button Grid.Row="0"  Grid.Column="2" Text="&#xf0d6; Espèce" Command="{Binding AddCommandEspece}" FontFamily="FontAwesome" StyleClass="Secondary"   HeightRequest="100" />
    
    
                        </Grid>              
    
                    </Grid>
    
                </StackLayout>
    
            </StackLayout>
            <Button StyleClass="Primary" Command="{Binding ConfirmCommand}" Text="CONFIRMER" />
        </StackLayout>
    
  • Deos69Deos69 Member ✭✭

    I have tried this at it works but it's not what I want...
    I have added a button in my grid :

       <Button Grid.Row="0"   Grid.Column="3" Text="&#xf00d;" Command="{Binding Path=BindingContext.RemoveArticle, Source={x:Reference TicketRecapView}}" FontFamily="FontAwesome" StyleClass="Secondary"   HeightRequest="100" />
    
    
    
    
        void Delete(PaymentLigne ligne)
            {
                PaymentLines.Remove(ligne);
            }
    
    
            Command<PaymentLigne> _RemoveArticle;
            public Command<PaymentLigne> RemoveArticle
            {
                get { return GetProperty(ref _RemoveArticle, () => new Command<PaymentLigne>(ligne => Delete(ligne))); }
            }
    

    Other problem the value Ligne is null

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    Do you want to achieve the result like following GIF?

    If yes, you should achieve the data binding of MenuItem like following code.

      <ViewCell.ContextActions>
            <MenuItem  Command="{Binding Path=BindingContext.DeleteCommand,Source={x:Reference Name=items}}" CommandParameter="{Binding .}"  Text="Delete" IsDestructive="True" />
            </ViewCell.ContextActions>
    

    You should add the CommandParameter and set the Source to the listview, because the MenuItem has no way of knowing which cell it belongs to. CommandParameter is available on MenuItem to store objects, such as the object behind the MenuItem's ViewCell.

    I upload my demo, you can refer to it.

  • Deos69Deos69 Member ✭✭

    Hello,

    I have tried your solution but no one of my android works too...

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    Did you use this code in Android emulator? Or android device? If it is a native android OS?

Sign In or Register to comment.