简体   繁体   中英

Xamarin Forms Collectionview not showing anything on UI even when binding is set and data is added to observable collection

I am quite a beginner so take it easy on me. I have a collection view which is bound to an observable collection. The observable collection receives data and has the items but the Collectionview doesn't display anything at all. Could someone please help me with this. Thanks.

XAML

        <CollectionView Grid.Row="1" ItemsSource="{Binding Fav}" x:Name="CVWatchItems" SelectionMode="Single" SelectionChanged="CVWatchItems_SelectionChangedAsync">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Padding="8, 8, 8, 0">
                        <Frame BorderColor="LightGray" CornerRadius="0" HasShadow="True" Padding="5">
                            <Grid Padding="0" ColumnSpacing="0" RowSpacing="0" Margin="2">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="120"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>

                                <ffimageloading:CachedImage Source="{Binding SingleimageUrl}" Aspect="AspectFill" WidthRequest="120" HeightRequest="100" Grid.Row="0" Grid.Column="0"/>

                                <Grid Grid.Row="0" Grid.Column="1" Padding="5">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Label Padding="0, 0, 0, 3" Text="{Binding Title}" LineBreakMode="TailTruncation" TextColor="Black" FontSize="Medium" Grid.Row="0"/>
                                    <Label Text="{Binding Price, StringFormat='Nu.{0}'}" FontSize="Small" TextColor="Black"  Grid.Row="1"  HorizontalOptions="StartAndExpand" />
                                    <Grid Grid.Row="2">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="7*"/>
                                            <ColumnDefinition Width="Auto"/>
                                        </Grid.ColumnDefinitions>

                                        <Label Text="{Binding location}" FontSize="Small" TextColor="Gray" Grid.Column="0" HorizontalOptions="StartAndExpand" VerticalOptions="EndAndExpand"/>
                                        <!--Watchlist Icon-->
                                        <Image Source="{Binding Favorite}" Grid.Column="1" Aspect="AspectFill" HeightRequest="28" Margin="2, 0" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand">
                                            <Image.GestureRecognizers>
                                                <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
                                                <!--Give ID to each ad and stored data is retrieved through id.-->
                                            </Image.GestureRecognizers>
                                        </Image>
                                    </Grid>
                                </Grid>

                            </Grid>
                        </Frame>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

Code behind

   public static ObservableCollection<Item> Fav { get; set; } = new ObservableCollection<Item>();
   public Watchlist ()
    {
        InitializeComponent ();
        NavigationPage.SetHasNavigationBar(this, false);
        NavigationPage.SetHasBackButton(this, false);

        CVWatchItems.SetBinding(CollectionView.ItemsSourceProperty, nameof(Fav));

        GetFavItems();
    }  

    private async void GetFavItems()
    {
        var MyFavorites = await Task.WhenAll(FirebaseDataHelper.GetFavoriteItems(allFavorites));
        
                foreach (var favorite in MyFavorites)
                {
                    if (favorite.Count > 0)
                    {
                        for (int i = 0; i < favorite.Count; i++)
                        {
                            favorite[i].IsFavorite = true;
                            if (!Fav.Any(s => s.Id == favorite[i].Id))
                                Fav.Add(favorite[i]);
                                
                        }
                    }
                }

               
      }

Thanks guys.

First your observable collection is static and you never set BindingContext to your page.

public static ObservableCollection<Item> Fav { get; set; } = new ObservableCollection<Item>();

Remove static keyword from the definition of Fav, change binding in your XAML (`assign a Name to your page) like:

<ContentPage x:Name="Root" ..../>

<CollectionView Grid.Row="1" ItemsSource="{Binding Source={x:Reference Name=Root}, Path=Fav}" ..../>

Also remove binding from your code behind. Last thing, your page has to implement INotifyPropertyChanged interface because you have to tell the page that this collection changed (your collection is filled after your async task is finished) So you have to raise PropertyChanged after your collection is filled.

But maybe in your case is better and easier to set ItemsSource without binding because you are not using MVVM . If you are in code behind of your page it is not necessary to use binding. You can set collectionview itemsource like:

 private async void GetFavItems()
    {
        var MyFavorites = await Task.WhenAll(FirebaseDataHelper.GetFavoriteItems(allFavorites));
        
                foreach (var favorite in MyFavorites)
                {
                    if (favorite.Count > 0)
                    {
                        for (int i = 0; i < favorite.Count; i++)
                        {
                            favorite[i].IsFavorite = true;
                            if (!Fav.Any(s => s.Id == favorite[i].Id))
                                Fav.Add(favorite[i]);
                                
                        }
                    }
                }

               CVWatchItems.ItemsSource = Fav;
      }

If you will use MVVM in your application you should use bindings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM