This is how I pass data from a parent page to a details page using Xamarin Forms and a ListView
- 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>
- 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); }
- 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); } }
- 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 }
- 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; } }
- 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>