I am trying to parse a json file of contacts into a list and display that list to the user in a picker on my page displaying the contact names.
I have a json file in the root of my project called "contacts.json" and its build action is set to embedded resource.
my contacts.json file
{
"contacts": [
{
"name": "JOE",
"email": "name@handle",
"phoneNumber": "123-456-7890"
},
{
"name": "JYM",
"email": "name@handle",
"phoneNumber": "123-456-7890"
}
]
}
my contact model:
public partial class RootObject
{
[JsonProperty("contacts")]
public List<Contact> Contacts { get; set; }
}
public partial class Contact
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
}
my page viewmodel where i implement a json parser
public partial class Page10 : BaseViewModel
{
private List<Contact> _contacts;
public List<InternalContact> contacts
{
get { return _contacts; }
set
{
_contacts = value;
OnPropertyChanged("contacts");
}
}
public Page10()
{
Title = "Spill Info";
contacts = GetJsonData();
}
private List<Contact> GetJsonData()
{
string jsonFileName = "contacts.json";
RootObject ObjContactList = new RootObject();
var assembly = typeof(Page10).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new System.IO.StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
//Converting JSON Array Objects into generic list
ObjContactList = JsonConvert.DeserializeObject<RootObject>(jsonString);
}
return ObjContactList.Contacts;
}
}
my baseViewModel
public class BaseViewModel : INotifyPropertyChanged
{
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
my page.xaml.cs
public partial class Page10 : ContentPage
{
public Page10()
{
InitializeComponent();
this.BindingContext = new contactviewmodel();
}
}
my page xaml
<ContentPage.Content>
<StackLayout>
<Picker Title="contacts" ItemsSource="{Binding contacts}" ItemDisplayBinding="{Binding Name}"/>
</StackLayout>
</ContentPage.Content>
After trying the above i get an empty picker when selected but i would expect to have seen JOE and JYM in the picker.
edit 1: I managed to get them to display in a list so i fiddled with trying to get them into a picker from there but i am only getting a list of my object types and not names in the picker. updated code to reflect changes. image of phone w/ contact list view and picker (cant embed pictures yet, not enough rep).
edit2: modified code to show @Cherry Bu- MSFT 's implementation
According to your description, I do one sample that you can take a look:
public partial class Page10 : ContentPage, INotifyPropertyChanged
{
private List<Contact> _contacts;
public List<Contact> contacts
{
get { return _contacts; }
set
{
_contacts = value;
RaisePropertyChanged("contacts");
}
}
public Page10()
{
InitializeComponent();
contacts = GetJsonData();
this.BindingContext = this;
}
private List<Contact> GetJsonData()
{
string jsonFileName = "contacts.json";
ContactList ObjContactList = new ContactList();
var assembly = typeof(Page10).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new System.IO.StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
//Converting JSON Array Objects into generic list
ObjContactList = JsonConvert.DeserializeObject<ContactList>(jsonString);
}
return ObjContactList.contacts;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public partial class ContactList
{
[JsonProperty("contacts")]
public List<Contact> contacts { get; set; }
}
public partial class Contact
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
}
<StackLayout>
<ListView x:Name="MyListView" ItemsSource="{Binding contacts}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Detail="{Binding Email}" Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Picker
x:Name="MyPicker"
ItemDisplayBinding="{Binding Name}"
ItemsSource="{Binding contacts}" />
</StackLayout>
Please don't forget to implement INotifyPropertychanged interface to nofity data updated.
Update:
If you want to get local Json file and display data in ListView using mvvm, please take a look the following code, I use Mvvm Mode.
public partial class Page10 : ContentPage
{
public Page10()
{
InitializeComponent();
this.BindingContext = new contactviewmodel();
}
}
public class contactviewmodel:ViewModelBase
{
private List<Contact> _contacts;
public List<Contact> contacts
{
get { return _contacts; }
set
{
_contacts = value;
RaisePropertyChanged("contacts");
}
}
public contactviewmodel()
{
contacts = GetJsonData();
}
private List<Contact> GetJsonData()
{
string jsonFileName = "contacts.json";
ContactList ObjContactList = new ContactList();
var assembly = typeof(Page10).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new System.IO.StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
//Converting JSON Array Objects into generic list
ObjContactList = JsonConvert.DeserializeObject<ContactList>(jsonString);
}
//Binding listview with json string
return ObjContactList.contacts;
}
}
The ViewModelBase is the class that implementing INotifyPropertyChanged:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Update again:
You can use the following code to get Json file.
private void LoadData()
{
var assembly = typeof(Page10).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
{
if (res.Contains("contacts1.json"))
{
Stream stream = assembly.GetManifestResourceStream(res);
using (var reader = new StreamReader(stream))
{
string data = "";
while ((data = reader.ReadLine()) != null)
{
}
}
}
}
}