Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

ListView Binding Itemssource doubt

tkruisetkruise Member ✭✭
edited November 2019 in Xamarin.Forms

I am trying to bind a response from a JsonConvert into a ListView, I´m pretty sure this can´t be done like this, do I really have to use Observable Collection?

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Net.Http;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using ModelsLayer;
using System.Collections.ObjectModel;

namespace TestXa1
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Profiles : ContentPage
    {
        public class RootObject2
        {
            public int Status { get; set; }
            public List<MdlProfiles> Response { get; set; }
        }


        public class WebInterface
        {
            public HttpClient _client;
            public WebInterface(HttpClient httpClient)
            {
                _client = httpClient;

            }

            ListView MyListView = new ListView();

            private const string url1 = "http://xxxx.xxx.xxx.xxxx/api/profiles";

            protected async void OnGetList()
            {
                var content = await _client.GetStringAsync(url1);
                var tr = JsonConvert.DeserializeObject<RootObject2>(content);
                MyListView.ItemsSource = tr.Response;

            }

        }
    }
}

And ListView

<?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="TestXa1.Profiles">
    <ListView x:Name="MyListView">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout>
                                <Label Text="{Binding Id}" />
                                <Label Text="{Binding FirstName}" />
                                <Label Text="{Binding LastName}" />
                                <Label Text="{Binding Zip}" />
                                <Label Text="{Binding City}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

And I´m getting nothing as a result, blanks, however, if I go to http://xxxx.xxx.xxx.xxxx/api/profiles, the json array is there, I just can´t seem to find the mistake.

Best Answer

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    It seems correct.

    Try with

    MyListView.ItemsSource =new ObservableCollection<MdlProfiles>( tr.Response);
    
  • YelinzhYelinzh Member, Xamarin Team Xamurai

    do I really have to use Observable Collection?

    If you want the ListView to automatically update as items are added, removed and changed in the underlying list, you'll need to use an ObservableCollection. ObservableCollection is defined in System.Collections.ObjectModel and is just like List, except that it can notify ListView of any changes.

    Tutorial about ListView Data Sources: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/data-and-databinding#itemssource

  • tkruisetkruise Member ✭✭

    Ooh I got it, but no, this list won´t ever change.
    Is it a problem to access "http://xxxx.xxx.xxx.xxxx/api/profiles"; if it´s located inside the IIS? This could be the problem as well. I mean, will the emulator "find" the IIS?

  • JohnHJohnH GBMember ✭✭✭✭✭

    @tkruise said:
    Ooh I got it, but no, this list won´t ever change.
    Is it a problem to access "http://xxxx.xxx.xxx.xxxx/api/profiles"; if it´s located inside the IIS? This could be the problem as well. I mean, will the emulator "find" the IIS?

    Put a breakpoint on the code that calls JSON deserialize and check what was returned from your web call.

  • tkruisetkruise Member ✭✭

    @JoeManke said:
    There is just so much wrong with this.

    You are just creating a ListView out of thin air, not even in the scope of a page. Giving it the same name does not make it correspond to the ListView you defined in your XAML.

    Then you are setting, not binding, the ItemsSource. There is a difference.

    You mean this: ListView MyListView = new ListView();?> @JoeManke said:

    There is just so much wrong with this.

    You are just creating a ListView out of thin air, not even in the scope of a page. Giving it the same name does not make it correspond to the ListView you defined in your XAML.

    Then you are setting, not binding, the ItemsSource. There is a difference.

    Thanks for the reply Joe
    About the ListView constructor, I thouht that was completely right, do I have to use a observableCollection to initiate it even if it´s a static list?

    A good bind would be like this, right? ( ItemsSource="{Binding Positions}" )

  • tkruisetkruise Member ✭✭

    I thought that ItemsSource="{Binding Positions}" wouldn´t return my items as columns..

  • JoeMankeJoeManke USMember ✭✭✭✭✭

    When you created this page, the .xaml.cs file should have come with a default constructor, which called the method InitializeComponent(). Where is that, and the rest of the code of your actual page class? Are you actually creating an instance of WebInterface somewhere and calling OnGetList(), or do you expect code to execute just because you wrote it? I don't know where to actually start helping you, because it seems like that might involve teaching you the basics of object-oriented programming, much less Xamarin.Forms.

    If you omitted any code from this page in your original post, share it. Then we can get into explaining what you've done wrong and fixing it.

  • tkruisetkruise Member ✭✭

    @JoeManke said:
    When you created this page, the .xaml.cs file should have come with a default constructor, which called the method InitializeComponent(). Where is that, and the rest of the code of your actual page class? Are you actually creating an instance of WebInterface somewhere and calling OnGetList(), or do you expect code to execute just because you wrote it? I don't know where to actually start helping you, because it seems like that might involve teaching you the basics of object-oriented programming, much less Xamarin.Forms.

    If you omitted any code from this page in your original post, share it. Then we can get into explaining what you've done wrong and fixing it.

    Yes, it is there:

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

    Only omitted this...

  • tkruisetkruise Member ✭✭
    edited November 2019

    The Master code that calls 'Profiles':

    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;

    namespace TestXa1
    {
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Master : ContentPage
    {
    public Master ()
    {
    InitializeComponent ();
    buttonA.Clicked += async (sender, e) =>
    {
    await App.NavigateMasterDetail(new Views.Profiles());
    };
    buttonB.Clicked += async (sender, e) =>
    {
    await App.NavigateMasterDetail(new Views.Partners());
    };

        }
    

    }
    }

    Once I (new Views.Profiles()); the InitializeComponent start @the Profiles page which is what it really should do and goes to:

    private void InitializeComponent() {
                global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(Profiles));
                MyListView = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.ListView>(this, "MyListView");
            }
    
  • tkruisetkruise Member ✭✭

    Updates, now I can see the variables response with the json array and the var profs with the number of array entries, however, still unable to populate the ListView in the emulator:

    using Newtonsoft.Json;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Threading.Tasks;
    using TestXa1.Models;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    
    namespace TestXa1.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class Profiles : ContentPage
        {
            public Profiles()
            {
                InitializeComponent();
                Task<List<MModels.MdlProfiles>> task = OnGetList();
            }
    
                public async Task<List<MModels.MdlProfiles>> OnGetList()
                {
                    HttpClient _client = new HttpClient();
                    var response = await _client.GetStringAsync("http://10.0.2.2:61902/api/profiles");
                    var profs = JsonConvert.DeserializeObject<List<MModels.MdlProfiles>> (response);
                    return profs;
                }
            }
        }
    

    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="TestXa1.Views.Profiles"
                 BackgroundColor="White">
    
        <ListView x:Name="MyListView" ItemsSource="{Binding task}">
    
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Vertical">
                            <Label Text="{Binding Id,StringFormat='ID: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding FirstName,StringFormat='First Name: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding LastName,StringFormat='Last Name: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding Zip,StringFormat='Zip: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding City,StringFormat='City: {0}'}" TextColor="Black"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
    
        </ListView>
    </ContentPage>
    
  • tkruisetkruise Member ✭✭

    OK, ListView is now displaying, fixed by:

        public partial class Profiles : ContentPage
        {
            public Profiles()
            {
                InitializeComponent();
                OnGetList();
            }
    
            protected async void OnGetList()
            {
                HttpClient _client = new HttpClient();
                var response = await _client.GetStringAsync("http://10.0.2.2:61902/api/profiles");
                var profs = JsonConvert.DeserializeObject<List<MModels.MdlProfiles>>(response);
                ObservableCollection<MModels.MdlProfiles> porfils = new ObservableCollection<MModels.MdlProfiles>(profs);
                MyListView.ItemsSource = porfils;
            }
    
        }
    

    However, it just displays two labels, the other ones are suppressed :smile:

    <?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="TestXa1.Views.Profiles"
                 BackgroundColor="White">
    
        <ListView x:Name="MyListView" HasUnevenRows="True">
    
            <ListView.ItemTemplate>
                <DataTemplate>
    
                    <ViewCell>
                        <StackLayout Orientation="Vertical">
                            <Label Text="{Binding Id,StringFormat='ID: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding FirstName,StringFormat='First Name: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding LastName,StringFormat='Last Name: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding Zip,StringFormat='Zip: {0}'}" TextColor="Black"/>
                            <Label Text="{Binding City,StringFormat='City: {0}'}" TextColor="Black"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
    
        </ListView>
    </ContentPage>
    
  • YelinzhYelinzh Member, Xamarin Team Xamurai
    edited November 2019

    The ListView code is correct, please check the data of list 'profs'.

    var profs = JsonConvert.DeserializeObject<List<MModels.MdlProfiles>>(response);
    
  • tkruisetkruise Member ✭✭
    edited November 2019

    The ListView didn´t print out all of the Labels, had to concatenate all of the Models "get" values inside a string and voilá, binded everything inside one Label only, everything working now, thanks everyone!:
    Code Update:

    XAML:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="TestXa1.Views.Profiles"
                 BackgroundColor="White">
    
        <ListView x:Name="MyListView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Vertical">
                            <Label Text = "{Binding NewProperty}" TextColor = "Black"/>
                        </StackLayout>
                    </ViewCell>
    
                </DataTemplate>
            </ListView.ItemTemplate>
    
        </ListView>
    </ContentPage>
    

    Code-Behind:

        namespace TestXa1.Views
        {
            [XamlCompilation(XamlCompilationOptions.Compile)]
            public partial class Profiles : ContentPage
            {
                public Profiles()
                {
                    InitializeComponent();
                    OnGetList();
                }
    
                protected async void OnGetList()
                {
                    HttpClient _client = new HttpClient();
                    var response = await _client.GetStringAsync("http://10.0.2.2:61902/api/profiles");
                    var profs = JsonConvert.DeserializeObject<List<MModels.MdlProfiles>>(response);
                    ObservableCollection<MModels.MdlProfiles> porfils = new ObservableCollection<MModels.MdlProfiles>(profs);
                    MyListView.ItemsSource = porfils;
                }
    
            }
        }
    
Sign In or Register to comment.