Passing Data from collectionview to details page Shell Navigation

MrZeeIndo 161 Reputation points
2021-06-15T03:01:28.65+00:00

Hi,

I have a collection view 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 collection view. 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.

Thanks

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

            }

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();
        }
Developer technologies | .NET | Xamarin
Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.

0 comments No comments

Answer accepted by question author

Anonymous
2021-06-16T02:56:44.27+00:00

Hello,​

Welcome to our Microsoft Q&A platform!

Firstly, you can change the Command binding way in the Label.GestureRecognizers of CollectionView.

   <ContentPage.Content>  
           <StackLayout>  
               <CollectionView x:Name="petCollectionView"  ItemsSource="{Binding EmptyPetInfo}" SelectedItem="{Binding SelectedPet, Mode=OneWay}" SelectionChanged="CollectionView_SelectionChanged">  
                   <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 Path=BindingContext.NavToDetailCommand, Source={x:Reference Name=petCollectionView}}"   
                                       CommandParameter="{Binding .}">  
                                       </TapGestureRecognizer>  
                                   </Label.GestureRecognizers>  
                               </Label>  
                           </Grid>  
                       </DataTemplate>  
                   </CollectionView.ItemTemplate>  
               </CollectionView>  
           </StackLayout>  
       </ContentPage.Content>  

Then, you can get the current model in the OnNav method of MyIDPageViewModel.cs. I do not have firebase, So I add static data for testing.

Here is MyIDPageViewModel.cs.

   using System;  
   using System.Collections.Generic;  
   using System.Text;  
   using System.Collections.ObjectModel;  
   using System.ComponentModel;  
   using System.Runtime.CompilerServices;  
   using System.Text;  
   using Xamarin.Forms;  
   using System.Threading.Tasks;  
   using System.Windows.Input;  
   using System.Linq;  
     
   namespace ShellCollectionVPassData.ViewModels  
   {  
       class MyIDPageViewModel : INotifyPropertyChanged  
       {  
           FirebaseHelper firebaseHelper = new FirebaseHelper();  
           public ICommand 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($"PetDetailsPage?name={PetDetailsPage.PetName}");  
           }  
     
           public async void CreatePetProfileCollection()  
           {  
               var petProfiles =  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 =  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  
       }  
     
       internal class FirebaseHelper  
       {  
           ObservableCollection<PetProfile> petProfiles;  
           public FirebaseHelper()  
           {  
               petProfiles = new ObservableCollection<PetProfile>();  
               petProfiles.Add(new PetProfile() { PetName = "Pet 1", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 2", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 3", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 4", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 5", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 6", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
               petProfiles.Add(new PetProfile() { PetName = "Pet 7", UserEmail = "******@test.com", Breed = "Breed1", CareInformation = "info", DOB = "dd", Gender = "male", Weight = "210" });  
           }  
            
           internal ObservableCollection<PetProfile> GetAllUserPetInfos()  
           {  
               // throw new NotImplementedException();  
     
              
     
               return petProfiles;  
           }  
     
           internal PetProfile GetPet(string petName)  
           {  
               //throw new NotImplementedException();  
     
            return petProfiles.Where(a => a.PetName == petName).FirstOrDefault();  
     
           }  
     
           //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();  
           //}  
       }  
     
       public class PetProfile  
       {  
           public string PetName { get; set; }  
           public string UserEmail { get; set; }  
           public string Breed { get; set; }  
     
           public string DOB { get; set; }  
     
           // Gender = groupitems.Gender, Weight = groupitems.Weight, CareInformation = groupitems.CareInformation  
     
           public string Gender { get; set; }  
     
           public string Weight { get; set; }  
     
           public string CareInformation { get; set; }  
       }  
   }  

I change your navigate way with await Shell.Current.GoToAsync($"PetDetailsPage?name={PetDetailsPage.PetName}"); in above MyIDPageViewModel.cs. And you need to RegisterRoute for PetPage and PetDetailsPage in the AppShell.xaml.cs code

   public partial class AppShell : Xamarin.Forms.Shell  
       {  
           public AppShell()  
           {  
               InitializeComponent();  
               Routing.RegisterRoute(nameof(ItemDetailPage), typeof(ItemDetailPage));  
               Routing.RegisterRoute(nameof(NewItemPage), typeof(NewItemPage));  
               Routing.RegisterRoute(nameof(PetPage), typeof(PetPage));  
               Routing.RegisterRoute(nameof(PetDetailsPage), typeof(PetDetailsPage));  
           }  
     
       }  

In the end, open the PetDetailsPage.xaml.cs, you need to add [QueryProperty(nameof(PetName), "name")] attribute above the PetDetailsPage .cs. Then move RetrivePetInfo method to the OnAppearing method, because when you execute RetrivePetInfo in PetDetailsPage's constructor, PetNamedo not get the value at that time.

   [XamlCompilation(XamlCompilationOptions.Compile)]  
       [QueryProperty(nameof(PetName), "name")]  
       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();  
               
     
           }  
     
           protected override void OnAppearing()  
           {  
               base.OnAppearing();  
               RetrivePetInfo();  
           }  
           private async void RetrivePetInfo()  
           {  
               var pet =  firebaseHelper.GetPet(PetName);  
               if (pet != null)  
               {  
                   petname.Text = pet.PetName;  
               }  
     
           }  
       }  
   }  

For more navigate details in Shell, you can refer to this thread:

https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#pass-data

Here is running screenshot.

105919-image.png After click the viewProfile 105926-image.png

Best Regards,

Leon Lu


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Was this answer helpful?

1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.