Usman Zafer
Usman Zafer

Reputation: 1361

INotifyPropertyChanged ListView

I am new to Xamarin Forms and trying to implement Infinite Loop Functionality in my app. The sample code that i followed is working fine and i have managed to integrate it into my app successfully.

The problem is that i am unable to find out how to change the source of the listview from the code.

I intend to have buttons above my listview (As in the following Image) and upon click the source of the listView should change.

Image

This is how my code looks like

 <ContentPage.BindingContext>
    <local:MainViewModel />
</ContentPage.BindingContext>

<StackLayout>

    <ListView  x:Name="tyres_listview" ItemsSource="{Binding Items}"
                       HasUnevenRows="True" SeparatorVisibility="None"  >

        <ListView.Behaviors>
            <extended:InfiniteScrollBehavior IsLoadingMore="{Binding IsBusy}" />
        </ListView.Behaviors>
        <ListView.ItemTemplate>

            <DataTemplate>
                <ViewCell>

                    <StackLayout>
                        <Grid Margin="10" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="0.25*"></ColumnDefinition>

                                <ColumnDefinition Width="0.75*"></ColumnDefinition>
                            </Grid.ColumnDefinitions>

                            <StackLayout  Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Margin="5,5,5,10">
                                <Image  Source="{Binding image_url}"  >
                                </Image>
                            </StackLayout>
                            <StackLayout Grid.Column="1" Spacing="0" >
                                <Label Text="{Binding name}" FontAttributes="Bold" FontSize="Small" Margin="0,5,5,0" VerticalOptions="Center" ></Label>
                                <Label  Text="{Binding brand}" VerticalOptions="Center" FontSize="Micro"  ></Label>
                                <Label  Text="{Binding item_id}" VerticalOptions="Center" FontSize="Micro"  ></Label>

                                <StackLayout Orientation="Horizontal" x:Name="sl_db" >
                                    <Image Source="fuel.png" ></Image>
                                    <Label Text="{Binding fuel_type}"></Label>
                                    <Image Source="weather.png"></Image>
                                    <Label Text="{Binding wheather_type }"></Label>
                                    <Image Source="volume.png"  ></Image>
                                    <Label Text="{Binding noise}"></Label>
                                    <Label Text="dB"></Label>
                                </StackLayout>


                                <StackLayout Orientation="Horizontal">
                                    <Image></Image>
                                    <Label Text="{Binding rated_count }"></Label>
                                </StackLayout>

                                <StackLayout Orientation="Horizontal">
                                    <Label Text="Price: " VerticalOptions="Center"></Label>
                                    <Label Text="{Binding price }" VerticalOptions="Center" TextColor="Green"></Label>
                                    <Label Text=" EUR" VerticalOptions="Center"></Label>

                                </StackLayout>
                                <StackLayout Orientation="Horizontal">
                                    <StackLayout.GestureRecognizers>
                                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_1" >

                                        </TapGestureRecognizer>
                                    </StackLayout.GestureRecognizers>
                                    <StackLayout BackgroundColor="Red" Orientation="Horizontal" Margin="5" >
                                        <Image Source="shoppingcart.png" Margin="10,0,0,0"></Image>
                                        <Label Text="Add to Cart" VerticalOptions="Center" HorizontalOptions="EndAndExpand" Margin="0,0,10,0" ></Label>
                                    </StackLayout>
                                    <Image x:Name="button_info"  Source="info.png" >

                                        <Image.GestureRecognizers>
                                            <TapGestureRecognizer Tapped="button_info_Clicked"></TapGestureRecognizer>
                                        </Image.GestureRecognizers>

                                    </Image>
                                </StackLayout>

                            </StackLayout>

                        </Grid>
                    </StackLayout>

                </ViewCell>

            </DataTemplate>

        </ListView.ItemTemplate>

        <ListView.Footer>
            <Grid Padding="6" IsVisible="{Binding IsBusy}">
                <!-- set the footer to have a zero height when invisible -->
                <Grid.Triggers>
                    <Trigger TargetType="Grid" Property="IsVisible" Value="False">
                        <Setter Property="HeightRequest" Value="0" />
                    </Trigger>
                </Grid.Triggers>
                <!-- the loading content -->
                <Label Text="Loading..." TextColor="DeepPink" FontSize="20" FontAttributes="Bold" VerticalOptions="Center" HorizontalOptions="Center" />
            </Grid>
        </ListView.Footer>
    </ListView>
    <Button Clicked="button_Change_Order_Clicked"></Button>
</StackLayout>

 public class MainViewModel : INotifyPropertyChanged
{
    private bool _isBusy;
    private const int PageSize = 10;
    readonly DataService _dataService = new DataService();

    public InfiniteScrollCollection<Product_Search> Items { get; }

    public bool IsBusy
    {
        get => _isBusy;
        set
        {
            _isBusy = value;
            OnPropertyChanged();
        }
    }
    public MainViewModel()
    {
        Items = new InfiniteScrollCollection<Product_Search>
        {
            OnLoadMore = async () =>
            {
                IsBusy = true;

                // load the next page
                var page = Items.Count / PageSize;
                var items = await _dataService.GetItemsAsync(page, PageSize);

                IsBusy = false;

                // return the items that need to be added
                return items;
            },
            OnCanLoadMore = () =>
            {
                return Items.Count < 44;
            }
        };

        DownloadDataAsync();
    }

    private async Task DownloadDataAsync()
    {
        var items = await _dataService.GetItemsAsync(pageIndex: 0, pageSize: PageSize);
        Items.AddRange(items);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

}

Any help would be of great importance.

Upvotes: 1

Views: 1566

Answers (1)

polkduran
polkduran

Reputation: 2551

Your ListView.Items property is already bound to your MainViewModel.Items property, a PropertyChanged event needs to be triggered to signal a change on the property value (corresponding to the property itself or its content if InfiniteScrollCollection<> is an Observable collection).

When you would want to replace the Items source you can give it a new value, signal it has changed and your ListView might be refreshed:

private InfiniteScrollCollection<Product_Search> _items;
public InfiniteScrollCollection<Product_Search> Items 
{ 
    get { return _items; }
    set
    {
        _items = value;
        OnPropertyChanged();
    }
}

Upvotes: 2

Related Questions