question

10918804 avatar image
0 Votes"
10918804 asked CherryBu-MSFT commented

How to BindableLayout.SetItemsSource?

Hi,

I have the following json output:

 [
     {
         "user_id": "1",
         "user_name": "John Mathews",
         "is_active": "1",
         "country_code": "US"
     }
 ]


my class:

 class CreditData
 {
     public string user_id { get; set; }
     public string user_name { get; set; }
     public string country_code { get; set; }
 }


and I am trying the BindableLayout for the first time.

I set the binding to the Grid this way:

 var data = JsonSerializer.Deserialize<ObservableCollection<CreditData>>(result);

also tried:

 List<CreditData> data = JsonSerializer.Deserialize<List<CreditData>>(result);


In XAML, I am setting the value:

 <Label Text="{Binding user_name}" />

but I am not getting any value, instead, I am getting:

MyApp.About+CeditsData





I don't have this issue when I bind to the ListView like this:

 ListViewPendingApproval.IsVisible = true;



Kindly help...




dotnet-csharpdotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

CherryBu-MSFT avatar image
1 Vote"
CherryBu-MSFT answered CherryBu-MSFT commented

Hello,

Welcome to our Microsoft Q&A platform!

From your description, you want to bind Json data to Grid, if you want to add Json.json in your project, you need to modify your Json data, please take a look the following code:

 {
   "credits": [
     {
       "user_id": "1",
       "user_name": "John Mathews",
       "is_active": "1",
       "country_code": "US"
     }
   ]
 }

Then set Json file build action as Embedded resource


Finally, convert Json to object, binding to Grid. My project name is FormsSample

  <Grid BindableLayout.ItemsSource="{Binding credits}">
                 <BindableLayout.ItemTemplate>
                     <DataTemplate>
                         <StackLayout>
                             <Label Text="{Binding user_id}" />
    
                             <Label Text="{Binding user_name}" />
                             <Label Text="{Binding country_code}" />
                         </StackLayout>
                     </DataTemplate>
                 </BindableLayout.ItemTemplate>
             </Grid>
    
 public partial class Page30 : ContentPage
     {
         private List<CreditData> _credits;
         public List<CreditData> credits
         {
             get { return _credits; }
             set
             {
                 _credits = value;
    
             }
         }   
         public Page30()
         {
             InitializeComponent();
    
              credits= getdata();
             this.BindingContext = this;
         }
         private List<CreditData> getdata()
         {
             CreditList ObjContactList = new CreditList();
                              
             var assembly = typeof(simplecontrol.Page30).GetTypeInfo().Assembly;
          
             Stream stream = assembly.GetManifestResourceStream("FormsSample.json2.json");
             using (var reader = new System.IO.StreamReader(stream))
             {
                 var jsonString = reader.ReadToEnd();
    
                 //Converting JSON Array Objects into generic list    
                 
                 ObjContactList = JsonConvert.DeserializeObject<CreditList>(jsonString);
             }
             //Binding listview with json string     
             return ObjContactList.credits;
         }
     }
    
     public class CreditList
     {
         public List<CreditData> credits { get; set; }
     }
     public class CreditData
     {
         public string user_id { get; set; }
         public string user_name { get; set; }
         public string country_code { get; set; }
     }


Update:

I think you have problem using JsonConvert.DeserializeObject<> method, suggest you to create new class CreditList, contains List<CreditData> credits property

   public class CreditList
         {
             //[JsonProperty("credits")]
             public List<CreditData> credits { get; set; }
         }

then converting JSON Array Objects into generic list.

  CreditList ObjContactList = new CreditList();
             ObjContactList = JsonConvert.DeserializeObject<CreditList>(result);
             List<CreditData> data = ObjContactList.credits;
    
             //ListViewCredits.ItemsSource = data;
             BindableLayout.SetItemsSource(GridCredits, data);

I install Newtonsoft.Json, to convert JSON Array Objects into generic list.

Update again:

I use System.Json to test at my side, I have no problem and I can get value, I guess that you have some problem for Grid BindableLayout.ItemTemplate, do you create BindableLayout.ItemTemplate in xaml or code behind?

Binding Grid by Xaml:

   <Grid x:Name="GridCredits">
                 <BindableLayout.ItemTemplate>
                     <DataTemplate>
                         <StackLayout>
                             <Label Text="{Binding user_id}" />
    
                             <Label Text="{Binding user_name}" />
                             <Label Text="{Binding country_code}" />
                         </StackLayout>
                     </DataTemplate>
                 </BindableLayout.ItemTemplate>
             </Grid>

Binding Grid by code behind:

   DataTemplate template = new DataTemplate(() =>
             {
    
                 StackLayout layout = new StackLayout() { Orientation = StackOrientation.Vertical };
                 Label label1 = new Label();
                 label1.SetBinding(Label.TextProperty, "user_id");
                 Label label2 = new Label();
                 label2.SetBinding(Label.TextProperty, "user_name");
                 Label label3 = new Label();
                 label3.SetBinding(Label.TextProperty, "country_code");
                 layout.Children.Add(label1);
                 layout.Children.Add(label2);
                 layout.Children.Add(label3);
                 return layout;
    
             });
             BindableLayout.SetItemTemplate(GridCredits, template);
             BindableLayout.SetItemsSource(GridCredits, credits);


Update more:

I test your project, and find you set BindableLayout.SetItemsSource, but the BindableLayout.ItemTemplate attached property isn't set, adding some Columns and Rows in Gird, it is one problem.

Then you get List<CreditData>, it is IEnumerable collection, The Grid is not correct control, The previous data will be overwritten by the following data. If you just want to layout, I suggest you can use Stacklayout.

  <StackLayout x:Name="GridCredits">
               
             <BindableLayout.ItemTemplate>
                 <DataTemplate>
                     <StackLayout Orientation="Horizontal">
                         <Image
                             Margin="5"
                             HeightRequest="45"
                             Source="{Binding country_flag}"
                             VerticalOptions="Center"
                             WidthRequest="45" />
                         <Label Text="{Binding user_name}" />
    
                     </StackLayout>
                 </DataTemplate>
             </BindableLayout.ItemTemplate>
               
         </StackLayout>

Best Regards,

Cherry Bu


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.





· 10
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I don't have a local json file. it's coming from my PHP result using below code:

 var client = new HttpClient();
    
 client.BaseAddress = new Uri("https://www.domain.com/getcredits.php");
    
 var content = new FormUrlEncodedContent(new[]
 {
     new KeyValuePair<string, string>("language", "EN")
 });
    
 var response = await client.PostAsync("https://www.domain.com/getcredits.php", content);
    
 if (response.IsSuccessStatusCode)
 {
     var result = await response.Content.ReadAsStringAsync();
    
     // List<CreditData> data = JsonSerializer.Deserialize<List<CreditData>>(result);
     var data = JsonSerializer.Deserialize<ObservableCollection<CreditData>>(result);
    
     // ListViewCredits.ItemsSource = data;
     BindableLayout.SetItemsSource(GridCredits, data);
 }


0 Votes 0 ·

Hi @10918804 Please my update.

0 Votes 0 ·

Is there any way to do it from PHP itself so I don't have to go through all this headache? because as I am mentioned the code is working when binding to ItemSource and I don't want to create a mess by having different code for different place, it's better to do it in the backend and sent it ready to the C#..

Is that possible?

0 Votes 0 ·
Show more comments

I know, never had this issue with Newtonsoft as it was doing everything but need to get used to way System.Json does it. Will try it and let you know.

0 Votes 0 ·

Please see the issue in this sample project:

https://www.jassimrahma.net/TestBinadleLayout.zip


0 Votes 0 ·

Hi @10918804 I have download your sample to test, please see my update more.

1 Vote 1 ·

Hi @10918804 May I know whether your issue has been solved or not? If not, please share it in here. We can work together to figure it out.

0 Votes 0 ·