[英]CollectionView doesn't update with ObservableCollection as Sourcee
[英]CollectionView doesn't update unless I logout user
嗨,我正在使用 firebase 实时数据库构建 Xamarin 应用程序,如下所示:
我设法通过使用 useremail 作为键创建了一个显示用户所有宠物的集合视图。 但是我遇到了问题。 如果我在 addPetPage 的数据库中添加一个新宠物并返回到带有 collectionView 的页面,它不会更新集合视图,除非我注销用户然后重新登录。为什么会这样?
这是我的 ViewModel 代码
class MyIDPageViewModel : INotifyPropertyChanged
{
FirebaseHelper firebaseHelper = new FirebaseHelper();
public IList<PetProfile> source;
public ObservableCollection<PetProfile> PetInfo { get; private set; }
public IList<PetProfile> EmptyPetInfo
{
get => source;
private set
{
if (value != source)
{
source = value;
OnPropertyChanged(nameof(EmptyPetInfo));
}
}
}
public MyIDPageViewModel()
{
source = new List<PetProfile>();
CreatePetProfileCollection();
}
private async void CreatePetProfileCollection()
{
var petProfiles = await firebaseHelper.GetAllUserPetInfos();
if (petProfiles != null)
{
EmptyPetInfo = new ObservableCollection<PetProfile>();
foreach (var groupitems in petProfiles)
{
EmptyPetInfo.Add(new PetProfile() { PetName = groupitems.PetName, UserEmail = groupitems.UserEmail, Breed = groupitems.Breed, DOB = groupitems.DOB, Gender = groupitems.Gender, Weight = groupitems.Weight, CareInformation = groupitems.CareInformation });
}
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
ID xamlPage:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage.BindingContext>
<local:MyIDPageViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Label
Text="My Id"
VerticalOptions="Start"
HorizontalOptions="Start"
Padding="15"
FontSize="Title"
FontAttributes="Bold"
TextColor="Black"/>
<Label Text="Name:" FontSize="Subtitle" Margin="15,0" FontAttributes="Bold"/>
<Label x:Name="UserName" FontSize="Medium" Margin="15,0"/>
<Label Text="Email Address:" FontSize="Subtitle" Margin="15,0" FontAttributes="Bold"/>
<Label x:Name="UserEmail" FontSize="Medium" Margin="15,0"/>
<Label Text="Phone Number:" FontSize="Subtitle" Margin="15,0" FontAttributes="Bold"/>
<Label x:Name="UserPhoneNumber" FontSize="Medium" Margin="15,0"/>
<Label Text="Address:" FontSize="Subtitle" Margin="15,0" FontAttributes="Bold"/>
<Label x:Name="UserAddress" FontSize="Medium" Margin="15,0"/>
<Label Text="My Pets:" FontSize="Large" Margin="15,0" FontAttributes="Bold"/>
<CollectionView ItemsSource="{Binding EmptyPetInfo}" >
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Grid.Row="0"
Text="{Binding PetName}"
FontAttributes="Bold" />
<Label Grid.Row="0"
Grid.Column="2"
Text="View Profile"
FontAttributes="Italic"
VerticalOptions="End" />
<Label Grid.Column="1"
Grid.Row="0"
Text="{Binding PetName}"
FontAttributes="Bold" />
<Label Grid.Row="0"
Grid.Column="2"
Text="View Profile"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="+ Add pet" HorizontalOptions="Center" FontAttributes="Bold">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="AddaPet_Tapped"/>
</Label.GestureRecognizers>
</Label>
<Button Text="Edit" HorizontalOptions="End" Margin="15" Clicked="Edit_Clicked"/>
</StackLayout>
</ContentPage.Content>
Firebase 助手:
public async Task<List<PetProfile>> GetAllUserPetInfos()
{
var useremail = Preferences.Get("UserSignInEmail", "");
var PetProfiles = await GetAllPetInfos();
await firebase
.Child("PetProfiles")
.OnceAsync<PetProfile>();
return PetProfiles.Where(a => a.UserEmail == useremail).ToList();
}
将宠物添加到数据库代码
public async Task AddPetInfo(string petname, string breed, string dob, string weight, string gender, string careinformation)
{
var useremail = Preferences.Get("UserSignInEmail", "");
await firebase
.Child("petProfiles")
.PostAsync(new PetProfile() { UserEmail = useremail, PetName = petname, Breed = breed, DOB = dob, Weight = weight, Gender = gender, CareInformation = careinformation });
}
我会将 ViewModel 代码更改为如下所示:
class MyIDPageViewModel : INotifyPropertyChanged
{
FirebaseHelper firebaseHelper = new FirebaseHelper();
public ObservableCollection<PetProfile> EmptyPetInfo { get; }
= new ObservableCollection<PetProfile>();
public MyIDPageViewModel()
{
Task.Run(CreatePetProfileCollection);
}
private async Task CreatePetProfileCollection()
{
var petProfiles = await firebaseHelper.GetAllUserPetInfos();
if (petProfiles == null)
{
return;
}
foreach (var groupitems in petProfiles)
{
EmptyPetInfo.Add(
new PetProfile()
{
PetName = groupitems.PetName,
UserEmail = groupitems.UserEmail,
Breed = groupitems.Breed,
DOB = groupitems.DOB,
Gender = groupitems.Gender,
Weight = groupitems.Weight,
CareInformation = groupitems.CareInformation
}
);
}
}
async void
,除非您将其用于事件。 即使我在这里修改过的代码,我也会考虑将其更改为在生命周期方法而不是构造函数中获取项目的模式,因为您只是触发并忘记了Task
。 如果在滚动列表或触摸 CollectionView 之前项目仍未出现,则需要将用于将项目添加到ObservableCollection
的代码封装在一段编组回 UI 线程的代码中。 由于您使用的是 Xamarin.Forms,因此可以使用Device.BeginInvokeOnMainThread()
来完成。 在这种情况下,我会从 foreach 中提取一个方法:
private void AddPetInfos(IEnumerable<PetProfile> petInfos)
{
foreach (var groupitems in petProfiles)
{
EmptyPetInfo.Add(
new PetProfile()
{
PetName = groupitems.PetName,
UserEmail = groupitems.UserEmail,
Breed = groupitems.Breed,
DOB = groupitems.DOB,
Gender = groupitems.Gender,
Weight = groupitems.Weight,
CareInformation = groupitems.CareInformation
}
);
}
}
然后包装这个方法:
Device.BeginInvokeOnMainThread(AddPetInfos(petProfiles));
这将确保您在正确的线程上添加项目,以便ObservableCollection
通知正确线程上的视图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.