Home > Back-end >  Parsing local json file and displaying it in a CarouselView in Xamarin Forms
Parsing local json file and displaying it in a CarouselView in Xamarin Forms

Time:03-02

I am developing a mobile application using Xamarin.Forms, and for testing purposes I am trying to read a local json file and displaying its contents into a CarouselView. However, I am not able to do it: I am correctly parsing the file, but then it is not showed in the UI.

The xaml code (with only the CarouselView part) is as follows:

<!-- Carousel view with all the contents -->
        <CarouselView Grid.Row="1" 
                      Loop="False"
                      x:Name="visitChoicheCarousel"
                      ItemsSource="{Binding Rooms}">
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <StackLayout>
                        <Frame HasShadow="True" 
                               BorderColor="DarkGray" 
                               CornerRadius="5" 
                               Margin="20" 
                               HeightRequest="300" 
                               HorizontalOptions="Center" 
                               VerticalOptions="CenterAndExpand">
                            <StackLayout>
                                <Label Text="{Binding Contents.Name}"
                                       FontAttributes="Bold" 
                                       FontSize="Large" 
                                       HorizontalOptions="Center" 
                                       VerticalOptions="Center"
                                       AutomationProperties.IsInAccessibleTree="True"/>
                            </StackLayout>
                        </Frame>
                    </StackLayout>
                </DataTemplate>
            </CarouselView.ItemTemplate>
        </CarouselView>

The c# script that parses the file is as follows:

using System.Net.Http;
using System.Collections.ObjectModel;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using PalazzoVecchioDemo.Models;
using Newtonsoft.Json;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.Reflection;

namespace PalazzoVecchioDemo.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class VisitChoice : ContentPage
    {
        private const string _json = "rooms.json";

        public Room Rooms { get; set; } = new Room();

        public VisitChoice()
        {
            InitializeComponent();

            BindingContext = this;
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            var assembly = typeof(VisitChoice).GetTypeInfo().Assembly;
            Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{_json}");

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

                Rooms = JsonConvert.DeserializeObject<Room>(jsonString);
            }
        }
    }
}

The class that contains the de-serialized file is as follows:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace PalazzoVecchioDemo.Models
{
    public class Rootobject
    {
        public Room[] Rooms { get; set; }
    }

    public class Room
    {
        [JsonProperty("ID")]
        public string ID { get; set; }
        public Content[] Contents { get; set; }
    }

    public class Content
    {
        [JsonProperty("Name")]
        public string Name { get; set; }
        [JsonProperty("ImageURI")]
        public string ImageURI { get; set; }
    }
}

Could anyone help me?

CodePudding user response:

first, your ItemsSource needs to be an IEnumerable

this is wrong, Room is a single Room object

ItemsSource="{Binding Rooms}"

you probably want to do this, because Contents is an array

ItemsSource="{Binding Rooms.Contents}"

then also change this

Text="{Binding Contents.Name}"

to this

Text="{Binding Name}"

finally, either assign the BindingContext after you load the data, or use INotifyPropertyChanged to signal that Rooms has been updated

CodePudding user response:

public partial class VisitChoice : ContentPage, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private const string FileName = "Room.json";

    private List<Room> _rooms;
    public List<Room> Rooms
    {
        get => _rooms;
        set
        {
            _rooms = value;
            NotifyPropertyChanged();
        }
    }

    public VisitChoice()
    {
        InitializeComponent();
        BindingContext = this;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();


        var assembly = IntrospectionExtensions.GetTypeInfo(typeof(VisitChoice)).Assembly;
        var stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{FileName}");

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

            Rooms = JsonConvert.DeserializeObject<List<Room>>(jsonString);
        }
    }
}
  • Related