Passing Data from CollectionView to details page Shell Navigation

333 Views Asked by At

I have a CollectionView with a list of names and a label view profile. When I click view profile I want to navigate to the details page. However I am confused with the shell navigation and how to pass data from one page to another.

As well as with CollectionView. This is my first time working with it. I am clicking on viewprofile and navigating to the details page however the data I pass through doesn't pass. The PetName doesn't appear as I guess there is no value. I am using a command to call navigation.

I guess I am unsure how to get the Petsname when I click view profile then pass it on.

MyIDPageViewModel:

 class MyIDPageViewModel : INotifyPropertyChanged
 {
     FirebaseHelper firebaseHelper = new FirebaseHelper();
     public Command NavToDetailCommand { get; set; }

     public ObservableCollection<PetProfile> source;
     public ObservableCollection<PetProfile> PetInfo { get; private set; }
     public ObservableCollection<PetProfile> EmptyPetInfo
     {
         get => source;
         private set
         {
             if (value != source)
             {
                 source = value;
                 OnPropertyChanged(nameof(EmptyPetInfo));
             }
         }
     }

     public MyIDPageViewModel()
     {
         source = new ObservableCollection<PetProfile>();           
         CreatePetProfileCollection();
         NavToDetailCommand = new Command<PetProfile>(OnNav);
     }

     private async void OnNav(PetProfile PetDetailsPage)
     {           

         if (PetDetailsPage == null)
             return;

         await Shell.Current.GoToAsync($"//MyIDPage/PetDetailsPage?PetName={PetDetailsPage.PetName}");
     }

     public 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 });
             }
         }
     }

        
     public async void Refresh()
     {
         EmptyPetInfo.Clear();
         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

My collection View:

<CollectionView  ItemsSource="{Binding EmptyPetInfo}" SelectedItem="{Binding SelectedPet, Mode=OneWay}" SelectionChanged="OnCollectionViewSelectionChanged">
             <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="Image Goes Here"
                                FontAttributes="Bold" />
                         <Label Grid.Column="1"
                                Grid.Row="0"
                                Text="{Binding PetName}"
                                FontAttributes="Bold"
                                x:Name="labelpetname"/>
                         <Label  Grid.Row="0"
                                 Grid.Column="2"
                                 Text="View Profile"
                                 FontAttributes="Italic"
                                 VerticalOptions="End"                                
                                 >
                             <Label.GestureRecognizers>
                                 <TapGestureRecognizer Command="{Binding NavToDetailCommand, Source={
                                 RelativeSource AncestorType={x:Type local:MyIDPageViewModel}
                             }}"
                             CommandParameter="{Binding .}">
                                 </TapGestureRecognizer>
                             </Label.GestureRecognizers>
                         </Label>
                     </Grid>
                 </DataTemplate>
             </CollectionView.ItemTemplate>
         </CollectionView>

PetDetailsPage:

public partial class PetDetailsPage : ContentPage
{
    FirebaseHelper firebaseHelper = new FirebaseHelper();
    private string _PetName;
    public string PetName
    {
        get => _PetName;
        set
        {
            if (value != _PetName)
            {
                _PetName = value;
            }
        }
    }

    public PetDetailsPage()
    {
        InitializeComponent();
        RetrivePetInfo();

    }

    private async void RetrivePetInfo()
    {
        var pet = await firebaseHelper.GetPet(_PetName);
        if (pet != null)
        {
            petname.Text = pet.PetName;
        }

    }

    private void Button_Clicked(object sender, EventArgs e)
    {

    }
}

Code for retrieving PetInfo from firebase:

public async Task<PetProfile> GetPet(string petname)

{ var useremail = Preferences.Get("UserSignInEmail", "");

     var PetProfiles = await GetAllPetInfos();
     await firebase
       .Child("PetProfiles")
       .OnceAsync<PetProfile>();
     return PetProfiles.Where(a => a.UserEmail == useremail && a.PetName == petname).FirstOrDefault();
 }
1

There are 1 best solutions below

0
ColeX On
  1. As Cfun mentioned in comment , Add a QueryProperty attribute above the class .
  [QueryProperty(nameof(PetName), "PetName")]
  public partial class PetDetailsPage : ContentPage{}
  1. set method of propery PetName is invoked later than class constructor, so _PetName is null in RetrivePetInfo method , as a workaround , you could call RetrivePetInfo directly in set method instead in constructor .
  public string PetName
  {
      get => _PetName;
      set
      {
          if (value != _PetName)
          {
              _PetName = value;
              RetrivePetInfo();
          }
      }
  }