即使设置了绑定并将数据添加到可观察集合,Xamarin Forms Collectionview 也不会在 UI 上显示任何内容
Xamarin Forms Collectionview not showing anything on UI even when binding is set and data is added to observable collection
我是个新手,请放轻松。我有一个绑定到可观察集合的集合视图。可观察集合接收数据并包含项目,但 Collectionview 根本不显示任何内容。有人可以帮我解决这个问题吗?谢谢
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>
代码隐藏
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]);
}
}
}
}
谢谢大家。
首先,您的可观察集合是静态的,您从未将 BindingContext 设置到您的页面。
public static ObservableCollection<Item> Fav { get; set; } = new ObservableCollection<Item>();
从 Fav 的定义中删除静态关键字,更改 XAML 中的绑定(`为您的页面分配名称),例如:
<ContentPage x:Name="Root" ..../>
<CollectionView Grid.Row="1" ItemsSource="{Binding Source={x:Reference Name=Root}, Path=Fav}" ..../>
同时从后面的代码中删除绑定。最后一件事,你的页面必须实现 INotifyPropertyChanged 接口,因为你必须告诉页面这个集合改变了(你的集合在你的异步任务完成后被填充)所以你必须在你的集合被填充后引发 PropertyChanged。
但在您的情况下,在没有绑定的情况下设置 ItemsSource 可能更好也更容易,因为您没有使用 MVVM。
如果您在页面后面的代码中,则没有必要使用绑定。您可以像这样设置 collectionview itemsource:
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;
}
如果您将在您的应用程序中使用 MVVM,您应该使用绑定。
我是个新手,请放轻松。我有一个绑定到可观察集合的集合视图。可观察集合接收数据并包含项目,但 Collectionview 根本不显示任何内容。有人可以帮我解决这个问题吗?谢谢
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>
代码隐藏
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]);
}
}
}
}
谢谢大家。
首先,您的可观察集合是静态的,您从未将 BindingContext 设置到您的页面。
public static ObservableCollection<Item> Fav { get; set; } = new ObservableCollection<Item>();
从 Fav 的定义中删除静态关键字,更改 XAML 中的绑定(`为您的页面分配名称),例如:
<ContentPage x:Name="Root" ..../>
<CollectionView Grid.Row="1" ItemsSource="{Binding Source={x:Reference Name=Root}, Path=Fav}" ..../>
同时从后面的代码中删除绑定。最后一件事,你的页面必须实现 INotifyPropertyChanged 接口,因为你必须告诉页面这个集合改变了(你的集合在你的异步任务完成后被填充)所以你必须在你的集合被填充后引发 PropertyChanged。
但在您的情况下,在没有绑定的情况下设置 ItemsSource 可能更好也更容易,因为您没有使用 MVVM。 如果您在页面后面的代码中,则没有必要使用绑定。您可以像这样设置 collectionview itemsource:
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;
}
如果您将在您的应用程序中使用 MVVM,您应该使用绑定。