Pass Data to a Details Page in Xamarin Forms and ListView

This is how I pass data from a parent page to a details page using Xamarin Forms and a ListView

  1. On my MainPage.xaml file I have a ListView control populated with an list of data with an ItemTapped event.
    <StackLayout>
    <ListView x:Name="lstPoop" ItemTapped="lstPoop_ItemTapped" HasUnevenRows="true" BackgroundColor="SandyBrown"
    HorizontalOptions="FillAndExpand"> 
    <ListView.ItemTemplate>
    <DataTemplate>
    <ViewCell>
    <StackLayout VerticalOptions="FillAndExpand" HeightRequest="75" Orientation="Horizontal" Spacing="15">
    <Label HorizontalOptions="Start" Text="{Binding Title}" TextColor="Black" VerticalTextAlignment="Center" 
    FontSize="Header" Font="Bold, Medium" />
    </StackLayout>
    </ViewCell>
    </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    </StackLayout>
  2. the ListView ItemsSource is set in the MainPage.xaml.cs file
    protected async override void OnAppearing()
    {
    base.OnAppearing();
    if (App.PoopListEnum.Count == 0) {
    PoopEnum = await PoopModel.GetData();
    if (PoopEnum == null || PoopEnum.Count == 0)
    {
    await DisplayAlert("Error", "Error loading Poop", "Ok");
    }
    else
    {
    App.PoopListEnum = PoopEnum;
    }
    }
    PoopEnum = App.PoopListEnum;
    lstMain.ItemsSource = PoopEnum.OrderBy(x => x.Title);
    
    }
  3. My App.PoopListEnum list is instantiated in the App.xaml.cs file
    public partial class App : Application
    {
    
    public static List<Models.Poop> PoopListEnum = new List<Models.Poop>();
    
    public App()
    {
    InitializeComponent();
    
    MainPage = new MainPage();
    }
    
    protected override void OnStart()
    {
    PoopListEnum = new List<Models.Poop>();
    }
    
    protected override void OnSleep()
    {
    //PoopListEnum = null;
    }
    
    protected override void OnResume()
    {
    }
    
    private async void btnBackToilet_Clicked(object sender, EventArgs e)
    {
    await this.MainPage.Navigation.PopModalAsync(true);
    }
    }
  4. I navigate to the Details page as a modal, passing the data details as an object when the ItemTapped event is called when you tap on a row in the ListView. Notice how I de-select the ListView row by setting the SelectedItem to null.
    private async void lstPoop_ItemTapped(object sender, ItemTappedEventArgs e)
    {
    if (lstPoop.SelectedItem == null)
    return;
    
    Models.Poop p = e.Item as Models.Poop;
    await Navigation.PushModalAsync(new Details(p), true);
    
    ((ListView)sender).SelectedItem = null; // de-select the row
    }
  5. In the Details.xaml.cs file, I retrieve the object data in the Details constructor and set the Title and Description properties to their corresponding labels.
    public partial class Details : ContentPage
    
    {
    
    Models.Poop PoopDetails { get; set; }
    
    public Details(Models.Poop poop)
    
    {
    
    InitializeComponent();
    
    PoopDetails = poop as Models.Poop;
    
    }
    
    protected override void OnAppearing()
    
    {
    
    base.OnAppearing();
    
    lblDesc.Text = PoopDetails.Description;
    
    lblTitle.Text = PoopDetails.Title;
    
    }
    
    }
  6. The Details.xaml has 2 Labels a StackLayout all within a ScrollView
    <ScrollView>
    
    <StackLayout Orientation="Vertical">
    
    <StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand" Padding="20">
    
    <Label Text="{Binding Title}" x:Name="lblTitle" FontSize="Large" FontAttributes="Bold" VerticalOptions="Start" HorizontalOptions="StartAndExpand" />
    
    <Label Text="{Binding Description}" Margin="0,20" x:Name="lblDesc" FontSize="Medium" VerticalOptions="Start" HorizontalOptions="StartAndExpand" />
    
    </StackLayout>
    
    </StackLayout> 
    
    </ScrollView>