Home > Back-end >  Xamarin Listview Item Source Binding not working
Xamarin Listview Item Source Binding not working

Time:10-14

I have a small project that has two pages showing a list view. But one of my pages is not working in spite of beeing the same code with just small changes (names of props). The binding context it´s taking the information i need (the Patients list) but the page returns empty. In my other page with the same code the Viewlist works properly. Maybe i'm missing something or could be a typo error i really don't know what's happening. Please help me and if u have suggestions to improve my code please tell me i'm a begginer in xamarin forms.

XAML:

<ListView x:Name="appointmentListView"
          SeparatorVisibility="None"
          HasUnevenRows="true"
          ItemsSource="{Binding Appointments}">
    <ListView.Header>
        <Grid BackgroundColor="#03A9F4">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="10"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="80"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="10"/>
            </Grid.RowDefinitions>
        </Grid>
    </ListView.Header>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="15,10" HorizontalOptions="FillAndExpand" x:DataType="model:Appointment">
                    <Label  VerticalOptions="FillAndExpand" VerticalTextAlignment="Center" 
                Text="{Binding Patient}" 
                FontSize="24"/>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Code behind:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AppointmentListViewDetail : ContentPage
{
    public AppointmentListViewDetail()
    {
        InitializeComponent();

        BindingContext = new AppointmentListViewModel();

        appointmentListView.ItemSelected  = (s, e) =>
        {
            if (e.SelectedItem as Appointment != null)
            {
                Action goToPage = async () =>
                {
                    await PopupNavigation.Instance.PushAsync(new AppointmentDetailsPopup(e.SelectedItem as Appointment));
                    appointmentListView.SelectedItem = null;
                };
                goToPage.Invoke();
            }
        };
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        MessagingCenter.Subscribe<AppointmentListViewModel>(this, "Reload", (p) =>
        {
            BindingContext = p;
        });

        MessagingCenter.Subscribe<AppointmentFilterViewModel>(this, "Filter", (p) =>
        {
            string? nameFilter = p.NameFilter.Text;
            DateTime? startDateFilter = DateTime.ParseExact(p.StartDateFilter.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
            DateTime? finalDateFilter = DateTime.ParseExact(p.FinalDateFilter.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
            Status? statusFilter = (Status)Enum.Parse(typeof(Status), p.StatusFilter.Text);

            BindingContext = new AppointmentListViewModel(nameFilter, startDateFilter, finalDateFilter, statusFilter);
        });

    }

ViewModel:

public class AppointmentListViewModel
{
    ObservableCollection<Appointment> _appointments;
    public ObservableCollection<Appointment> Appointments
    {
        get { return _appointments; }
        set
        {
            _appointments = value;
            OnPropertyChanged(nameof(Appointments));
        }
    }

    public ICommand Filter { get; set; }

    public AppointmentListViewModel()
    {
        var getAppointmentsList = new Action(async () =>
        {
            Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().ToListAsync());
        });

        getAppointmentsList.Invoke();

    }
    public AppointmentListViewModel(string? patient, DateTime? startDate, DateTime? finalDate, Status? status)
    {
        var getPatientList = new Action(async () =>
        {
            Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().FilterSearchAsync(patient, startDate, finalDate, status));
        });

        getPatientList.Invoke();

    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


}

Model:

    public class Appointment
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public float Price { get; set; }

    public DateTime Date { get; set; }

    public Status PaymentStatus { get; set; }

    public string Patient { get; set; }

}

CodePudding user response:

I solved this problem using Task.Run().Wait(). I recommend using that if u are trying to get data from the database on your viewmodel.

ViewModel:

 public AppointmentListViewModel()
    {
        Task.Run(async () =>
        {
            Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().ToListAsync());
        }).Wait();
    }

Service that contains all operations related to the database:

    public AppointmentService()
    {
        string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "patient.db3");
        _database = new SQLiteAsyncConnection(dbPath);
        _database.CreateTableAsync<Appointment>().Wait();
    }


    public Task<List<Appointment>> ToListAsync()
    {
        return _database.Table<Appointment>().ToListAsync();
    }
  • Related