I am trying to show the medicineList data in the ListPage.xaml using ListView. I have checked the documentation but I don't find anything noticeable. I have looked at this doc and tried to follow it. But it is not working.
This is ListPage.xaml.cs
using MedicineAlert.Data;
using System.Text.Json;
namespace MedicineAlert.Pages;
public partial class ListPage : ContentPage
{
public List<MedicineData> MedicineList { get; set; }
public ListPage()
{
InitializeComponent();
// Retrieve the app's local data directory path
string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
// Combine the local data directory path with your desired subdirectory
string dbFolderPath = Path.Combine(localDataDirPath, "DB");
string filePath = Path.Combine(dbFolderPath, "data.json");
if(File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
MedicineList = JsonSerializer.Deserialize<List<MedicineData>>(json);
}
}
}
This is ListPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MedicineAlert.Pages.ListPage"
Title="ListPage"
x:Name="MedicinesPage">
<StackLayout>
<ListView
ItemsSource="{Binding MedicineList, Source={x:Reference MedicinesPage}}"
>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding MedicineName}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
And this is AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MedicineAlert.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MedicineAlert.Pages"
>
<TabBar>
<Tab
Title="Add"
Icon="add.png"
>
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate views:AddPage}"
Route="AddPage"
/>
</Tab>
<Tab
Title="List"
Icon="list.png"
>
<ShellContent
Title="List"
ContentTemplate="{DataTemplate views:ListPage}"
Route="ListPage"
/>
</Tab>
</TabBar>
</Shell>
The ListView in ListPage is not rendering. What could be the problem?
The reason the ListView
is not rendering is two-fold:
internal List<MedicineData> medicineList
is a field, but it should be a property as only properties can be used in binding expressionsItemsSource
binding is not pointing to the code-behindFirst, change the field into a property:
public List<MedicineData> MedicineList { get; }
after that, move the InitializeComponent();
call to the end of the constructor:
public ListPage()
{
// Retrieve the app's local data directory path
string localDataDirPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
// Combine the local data directory path with your desired subdirectory
string dbFolderPath = Path.Combine(localDataDirPath, "DB");
string filePath = Path.Combine(dbFolderPath, "data.json");
if(File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
MedicineList = JsonSerializer.Deserialize<List<MedicineData>>(json);
}
InitializeComponent();
}
This is required, because in your case the binding will only get evaluated once and that happens during the InitializeComponent();
call.
Finally, update the XAML as follows using a binding Source
which points to the name of the page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MedicineAlert.Pages.ListPage"
Title="ListPage"
x:Name="MedicinesPage">
<StackLayout>
<ListView
ItemsSource="{Binding MedicineList, Source={x:Reference MedicinesPage}}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding MedicineName}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Binding a page to its own code behind is also an option by setting BindingContext = this;
, but that's not necessary with this approach.
Note: It's not recommended to load data inside a constructor. You may want to rethink your code design here. If you need to update the List
frequently, you should replace it with an ObservableCollection
and make the property itself also observable. This is a common use case for the MVVM pattern.