How to bind to nested properties (generated from JSON) in Xamarin MVVM

AspiringApollo 21 Reputation points
2021-05-10T15:19:12.197+00:00

0

I need some advice regarding binding to nested properties in generated class from JSON using Json2C#. So I'm using firebase cloud functions and I get a returned json string. I used that string to generate the below classes.

public class BusinessReturnedModel
{
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Longitude
{
public string stringValue { get; set; }
public string valueType { get; set; }
}

public class Line2
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class City
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Postcode
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Line1
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class County
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Country
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Fields
{
    public Line2 line_2 { get; set; }
    public City city { get; set; }
    public Postcode postcode { get; set; }
    public Line1 line_1 { get; set; }
    public County county { get; set; }
    public Country country { get; set; }
}

public class MapValue
{
    public Fields fields { get; set; }
}

public class Address
{
    public MapValue mapValue { get; set; }
    public string valueType { get; set; }
}

public class Name
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class ProfilePicture
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class BusinessType
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Geohash
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class Latitude
{
    public string stringValue { get; set; }
    public string valueType { get; set; }
}

public class FieldsProto
{
    public Longitude longitude { get; set; }
    public Address address { get; set; }
    public Name name { get; set; }
    public ProfilePicture profile_picture { get; set; }
    public BusinessType business_type { get; set; }
    public Geohash geohash { get; set; }
    public Latitude latitude { get; set; }
}

public class Settings
{
    public string projectId { get; set; }
    public string firebaseVersion { get; set; }
    public string libName { get; set; }
    public string libVersion { get; set; }
}

public class Serializer
{
    public bool allowUndefined { get; set; }
}

public class BackoffSettings
{
    public int initialDelayMs { get; set; }
    public int maxDelayMs { get; set; }
    public double backoffFactor { get; set; }
}

public class ActiveClients
{
}

public class FailedClients
{
}

public class Promise
{
}

public class TerminateDeferred
{
    public Promise promise { get; set; }
}

public class ClientPool
{
    public int concurrentOperationLimit { get; set; }
    public int maxIdleClients { get; set; }
    public ActiveClients activeClients { get; set; }
    public FailedClients failedClients { get; set; }
    public bool terminated { get; set; }
    public TerminateDeferred terminateDeferred { get; set; }
}

public class Firestore
{
    public Settings _settings { get; set; }
    public bool _settingsFrozen { get; set; }
    public Serializer _serializer { get; set; }
    public string _projectId { get; set; }
    public int registeredListenersCount { get; set; }
    public int bulkWritersCount { get; set; }
    public BackoffSettings _backoffSettings { get; set; }
    public ClientPool _clientPool { get; set; }
}

public class Path
{
    public List<string> segments { get; set; }
    public string projectId { get; set; }
    public string databaseId { get; set; }
}

public class Converter
{
}

public class Ref
{
    public Firestore _firestore { get; set; }
    public Path _path { get; set; }
    public Converter _converter { get; set; }
}

public class ReadTime
{
    public int _seconds { get; set; }
    public int _nanoseconds { get; set; }
}

public class CreateTime
{
    public int _seconds { get; set; }
    public int _nanoseconds { get; set; }
}

public class UpdateTime
{
    public int _seconds { get; set; }
    public int _nanoseconds { get; set; }
}

public class BusinessItem
{
    public FieldsProto _fieldsProto { get; set; }
    public Ref _ref { get; set; }
    public Serializer _serializer { get; set; }
    public ReadTime _readTime { get; set; }
    public CreateTime _createTime { get; set; }
    public UpdateTime _updateTime { get; set; }
}

}

public class Record
{
public BusinessReturnedModel record;
}
What I'm trying to achieve is a binding to these properties, below is my XAML.

<ContentPage.Content>

<StackLayout>

    <CollectionView ItemsSource="{Binding Businesses}"
                SelectionMode="Single">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="businessReturned:BusinessReturnedModel">
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2" 
                       Source="{Binding what goes here!!!???}" 
                       Aspect="AspectFill"
                       HeightRequest="60" 
                       WidthRequest="60" />
                <Label Grid.Column="1" 
                       Text="{Binding}" 
                       FontAttributes="Bold" />
                <Label Grid.Row="1"
                       Grid.Column="1" 
                       Text="{Binding}"
                       FontAttributes="Italic" 
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

</StackLayout>

</ContentPage.Content>
And below is my View Model (well the parts that are relevant anyway..
public ICommand GetNearbyServicesCommand => new Command<List<BusinessItem>>(async (List<BusinessItem> businesses) => { BusinessList = await GetNearbyAsync(); });
public ObservableCollection<BusinessItem> Businesses { get; set; }

private List<BusinessItem> _businessList;
public List<BusinessItem> BusinessList
{
    get
    {
        return _businessList;
    }
    set
    {
        if (_businessList != value)
        {
            _businessList = value;
            Businesses = new ObservableCollection<BusinessItem>(value);
            OnPropertyChanged();
        }
    }
}

...//public async Task<List<BusinessItem>> GetNearbyAsync()
//Here is the after http client get etc..
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();

        var myDeserializedClass = JsonConvert.DeserializeObject<List<BusinessItem>>(content);

        Console.WriteLine(myDeserializedClass);

        return myDeserializedClass;

    }

//...
So the issue is that when I try Binding to the properties I can't. I've tried Binding Record.Name, Binding record.Name, Binding FieldsProto.etc... Nothing seems to work. I know I'm probably doing this completely wrong but I can't find any docs on nested property binding when it comes to binding to the response of a RESTful web service. Please help!!

Kind regards, Aspiring Apollo

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,261 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
9,973 questions
{count} votes

Accepted answer
  1. Alessandro Caliaro 4,181 Reputation points
    2021-05-10T15:46:58.17+00:00

    With the service you return a list of

    public class BusinessItem
     {
         public FieldsProto _fieldsProto { get; set; }
         public Ref _ref { get; set; }
         public Serializer _serializer { get; set; }
         public ReadTime _readTime { get; set; }
         public CreateTime _createTime { get; set; }
         public UpdateTime _updateTime { get; set; }
     }
    

    So you should Bind the ItemSource

      <CollectionView ItemsSource="{Binding BusinessList}"
    

    Not

    <CollectionView ItemsSource="{Binding Businesses}"
    

    And you should use

    ObservableColletcion 
    

    intead of

    List
    

    Then, when you bind BusinessList, you have to choose the property to bind in the DataTemplate.
    I don't know which is the property what is the image source.
    Maybe

    public ProfilePicture profile_picture { get; set; }

    Ok, you should bind something like

                Source="{Binding _fieldsProto.profile_picture.stringValue}" 
    

0 additional answers

Sort by: Most helpful