Xamarin MVVM Android - Method getting called multiple times

rfrk 0 Reputation points
2023-01-18T14:53:09.0433333+00:00

I'm using Xamarin with MVVM and i have a CollectionView of Products and a checkbox. I have a list of Products implementing INotifyPropertyChanged. By using EventToCommandBehavior i call a Command when a checkbox is checked, binding the object as a CommandParameter. This command calls a Method called CheckPrice. This method checks if the Found property of the object is true and proceeds if it meets the condition (the IsChecked of the checkbox is binded to the Checked property of the object). After this check, the object is updated and then the method RefreshList is called, this method makes the list receive a new list from the database.

The problem is, every time the list is updated (through the RefreshList method) and the Notify() method of the List set is called, the CheckPrice method is called multiple times until i click cancel on the DisplayPrompt.

This appears to happen every time i refresh the ItemsSource (the Products list on the viewmodel), and only when the list have at least one checked checkbox.

View XAML

The CollectionView on the View

<CollectionView ItemsSource="{Binding Products}" x:Name="List">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <CheckBox  Margin="0,-21,0,0" IsChecked="{Binding Found}">
                <CheckBox.Behaviors CachingStrategy="RetainElement">
                    <xct:EventToCommandBehavior                                                            
                        EventName="PropertyChanged"
                        Command="{Binding BindingContext.CheckPrice, Source={x:Reference List}" 
                        CommandParameter="{Binding .}" />
                </CheckBox.Behaviors>
            </CheckBox>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

ViewModel
The list of Products that acts as the ItemsSource for the CollectionView

public List<Product> Products
{
    get { return produtos; }
    set { produtos = value; Notify(); }
}

The method that is being called by the CheckPrice command

private async void UpdatePrice(Product product)
{
    var str = await App.Current.MainPage.DisplayPromptAsync("Product Found!", "Type the price", "Save", "Cancel", keyboard: Keyboard.Numeric);
    if (str != null)
    {
        product.Price = Decimal.Parse(str);
        App._productRepo.UpdateProduct(product);
        RefreshProd();
    }
}

The RefreshList method that is called everytime i add or remove something (also called on the constructor of the viewmodel)

public void RefreshList()
{
    this.Products = App._productRepo.GetProducts();
}    

Among a lot of things, i tried to use an ObservableCollection instead of a List implementing INotifyPropertyChanged and that solves the problem, but that way my RefreshList method won't work (i have to close the page then open it again to refresh).

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,293 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,239 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Taylor 48,046 Reputation points
    2023-01-18T15:20:48.2466667+00:00

    I believe the behavior is (mostly) correct given your code. If I understand it properly you are triggering the command on every PropertyChanged event of the checkbox. If you rebind the collection then I would wager you'd get at least 2 of these events per item and probably more.

    If you only want to call the command when the checkbox is checked then consider handling the CheckedChanged event instead. Otherwise I think you need to put an intermediate check to ensure you are reacting only to the property(ies) you care about.

    0 comments No comments