Search code examples
c#xamarinxamarin.formsxamarin.android

Can't output info from JSON on a ListView in Xamarin


I've been trying to learn Xamarin with MVVM and I'm still struggling. I've had issues mainly trying to output information from a JSON file in a ListView.
If I just ignore MVVM and add the code directly into the View, it works perfectly. However, when I try to use the code in the ViewModel, it can't find the binded Itemssource.
The code:
ListPageVM

using SaveUp.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using SaveUp.View;
using System.Reflection;
using System.Text;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace SaveUp.ViewModel
{
    public class ListPageVM : INotifyPropertyChanged
    {

        private ObservableCollection<MainModel> data;
        public ListPageVM()
        {
            var assembly = typeof(ListPageVM).GetTypeInfo().Assembly;
            Stream stream = assembly.GetManifestResourceStream("SaveUp.eintraege.json");

            using (var reader = new StreamReader(stream))
            {
                var json = reader.ReadToEnd();

                List<MainModel> dataList = JsonConvert.DeserializeObject<List<MainModel>>(json);
                data = new ObservableCollection<MainModel>(dataList);
                lw.ItemsSource = data;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ListPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SaveUp.View.ListPage"
             xmlns:viewModel="clr-namespace:SaveUp.ViewModel"
             x:DataType="viewModel:ListPageVM">
    <ContentPage.BindingContext>
        <viewModel:ListPageVM/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <ListView x:Name="lw"
                      Footer="">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding Geld}" Detail="{Binding Detail}"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

eintraege.json

[
  {
    "Geld": 500.00,
    "Detail": "Kaffee"
  },
  {
    "Geld": 250.00,
    "Detail": "Creme"
  },
  {
    "Geld": 100.00,
    "Detail": "Yogurt"
  }

]

Solution

  • first, this needs to have a public property

    private ObservableCollection<MainModel> data;
    

    should look like

    private ObservableCollection<MainModel> data;
    public ObservableCollection<MainModel> Data { 
      get
      {
         return data;
      {
      set
      {
         data = value;
         OnPropertyChanged();
      }
    }
    

    if you are using MVVM, then your VM doesn't directly interact with your view

    // get rid of this
    lw.ItemsSource = data;
    

    then in your XAML use binding to set the ItemsSource

    <ListView ItemsSource="{Binding Data}" ...