5
votes

I'm currently creating a page using a ListView that is populated by data I recover from a Web API.
I added 2 buttons : one to refresh the data and one to store the data locally on the device. The problem is : none of them work, the binding doesn't produce errors in the log so I'm guessing it does bind the command to the button, but when I click on it, the command is not called.

XAML

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer CommandParameter="{Binding ItemId}">
                            <TapGestureRecognizer.Command>
                                <Binding Source="{x:Reference Page}">
                                    <Binding.Path>BindingContext.ShowItemDataCommand</Binding.Path>
                                </Binding>
                            </TapGestureRecognizer.Command>
                        </TapGestureRecognizer>
                    </StackLayout.GestureRecognizers>
                    <Switch IsToggled="{Binding IsOffline}"/>
                    <StackLayout Orientation="Vertical">
                        <Label Text="{Binding ItemTitle}"/>
                        <Label Text="{Binding ItemDescription}" FontSize="Micro"/>
                    </StackLayout>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
<ListView.Footer>
    <StackLayout>
        <Button Text="Refresh items" HorizontalOptions="CenterAndExpand" Command="{Binding RefreshItemsCommand}"/>
        <Button Text="Save item data" HorizontalOptions="CenterAndExpand" Command="{Binding SaveItemData}"/>
    </StackLayout>
</ListView.Footer>
</ListView>

Commands in the ViewModel

public class ItemsViewModel : INotifyPropertyChanged
{
    (...)
    public ItemsViewModel() {
        (...)
        RefreshItemsCommand = new Command(GetItemsObservableCollection);
        TogglePacksAvailabilityCommand = new Command(async () =>
        {
            foreach (var i in Items.Where(i => i.IsOffline)) {
                await SaveItem(i.ItemId);
            }
        });
        (...)
    }
    (...)
    public ICommand RefreshItemsCommand { protected set; get; }
    public ICommand TogglePacksAvailabilityCommand { protected set; get; }
    (...)
}

The command I use for the GestureRecognizer works fine, only the buttons seem to not work, I tried to put Debug.WriteLine() in the called methods to see if they were executing, but they never write in the output log, so I assume they are not called at all.
So, what could be the reason for the buttons to not call their commands ?

1

1 Answers

11
votes

Seems, that Command looking for SaveItemData in BindingContext of ListView. But your commands placed in ViewModel. I'd like to suggest you my solution:

<Button Command="{Binding BindingContext.YourCommand, Source={x:Reference Page}"
        CommandParameter="{Binding BindingContext, Source={x:Reference SomeControl}"/>

It worked for me, hope it will help you!