繁体   English   中英

除非我注销用户,否则 CollectionView 不会更新

[英]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
                }
            );
        }
    }
  1. 如果您使用的是 ObservableCollection,则在属性上使用 RaisePropertyChanged 是没有意义的,只需实例化并重用该实例
  2. 您应该避免使用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.

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