Xamarin 表单读取本地 json 文件并显示在选择器中

Xamarin forms read local json file and display in picker

我正在尝试将一个 json 联系人文件解析为一个列表,并在我显示联系人姓名的页面上的选择器中将该列表显示给用户。

我的项目根目录中有一个名为 "contacts.json" 的 json 文件,其构建操作设置为嵌入资源。

我的contacts.json文件

{
  "contacts": [
    {
      "name": "JOE",
      "email": "name@handle",
      "phoneNumber": "123-456-7890"
    },
    {
      "name": "JYM",
      "email": "name@handle",
      "phoneNumber": "123-456-7890"
    }
  ]
}

我的联系方式:

    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; }
    }

我的页面视图模型,我在其中实现了 json 解析器

    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;
        }
    }

我的 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
    }

我的page.xaml.cs

public partial class Page10 : ContentPage
    {
        public Page10()
        {
            InitializeComponent();
            this.BindingContext = new contactviewmodel();
        }
    }

我的页面xaml

<ContentPage.Content>
        <StackLayout>
            <Picker Title="contacts" ItemsSource="{Binding contacts}" ItemDisplayBinding="{Binding Name}"/>    
        </StackLayout>
    </ContentPage.Content>

在尝试以上方法后,我在选择时得到一个空的选择器,但我希望在选择器中看到 JOE 和 JYM。

编辑 1: 我设法让它们显示在列表中,所以我摆弄着试图从那里将它们放入选择器中,但我只得到了我的列表选择器中的对象类型而不是名称。更新代码以反映更改。 image of phone w/ contact list view and picker(还不能嵌入图片,代表不够)。

edit2: 修改代码以显示@Cherry Bu- MSFT 的实现

根据你的描述,我做了一个样品,你可以看看:

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>

请不要忘记实施 INotifyPropertychanged 接口以更新 nofity 数据。

更新:

如果你想获取本地Json文件并使用mvvm在ListView中显示数据,请看下面的代码,我使用的是Mvvm模式。

 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;
    }

}

ViewModelBase 是 class 实现 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));
        }
    }
}

再次更新:

您可以使用以下代码获取 Json 文件。

 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)
                    {

                    }
                }
            }
        }
    }